Java进阶(第二期):package 包 && 抽象类和抽象方法 && 接口的实现 && 多态的实现 && 综合继承、接口、多态的使用。

2023年11月26日20:11:11

Java进阶(第二期)

一、package包的概念

  • package包,其实就是管理类的文件夹,用来存放文件类的。
  • 只需要注意,同类名不同包的情况下,重复的类名,需要使用带包名访问。

在这里插入图片描述

二、抽象类和抽象方法(abstract)

2.1 使用

抽象类:抽象类其实就是特殊的父类

抽象方法存活在抽象类中,并且继承后的子类必须重写抽象方法

  • + 抽象方法的定义格式:
      + public abstract 返回值类型   方法名(参数列表);
    + 抽象类定义格式:
      + public abstract class 类名 {
          
          }
    
  • 问题:特殊在哪里?
  • 回答;内部允许编写抽象方法

  • 问题:什么是抽象方法?
  • 回答:当我们将其共性的方法,抽取到父类之后,发现这个方法中无法给出具体明确(描述不清),而且这个方法,还是子类必须要有的方法,就可以设计为抽象方法。
  • 看下面代码:这样设计完全不合理,我想抽取到父类中,让两个动物子类继承父类。里面的方法通过父类继承。但是我发现,方法都是一样的,就是里面的逻辑不一样,此时就得用到了抽象类和抽象方法:

    不使用抽象类的代码如下:

    package com.liujintao.demo;
    
    public class Abstrcte {
          
          
        public static void main(String[] LiuJinTao) {
          
          
    
        }
    }
    class Animal {
          
          
        public void eat () {
          
          
            System.out.println("我是吃饭的方法");
        }
    }
    class dog {
          
          
        public void eat () {
          
          
            System.out.println("吃骨头");
        }
    }
    
    class pig {
          
          
        public void eat () {
          
          
            System.out.println("吃食料");
        }
    }
    

使用抽象类和抽象方法后的代码如下:

package com.liujintao.demo;

public class Abstrcte {
    
    
    public static void main(String[] LiuJinTao) {
    
    

    }
}
abstract class Animal {
    
    

    public abstract void eat (); // 抽象方法必须存在抽象类中!!!
}
class dog extends Animal {
    
    

    public void eat () {
    
    
        System.out.println("吃骨头");
    }
}
class pig extends Animal {
    
    

    public void eat () {
    
    

        System.out.println("吃食料");
    }
}

  • 经过改造,这就使用了抽象方法和抽象类实现了功能,让子类自己重写,补充些就滚蛋。
2.1 抽象类注意事项
  1. 抽象类不能实例化:
    • 如果抽象类允许创建对象,就可以调用内部没有方法体的抽象方法了,不合理。
  1. 抽象类存在构造方法:
    • 子类通过super方法进行访问父类构造方法
  2. 抽象类中可以存在普通方法:
    • 因为抽象中,除了抽象方法外,的普通方法,子类可以通过继承使用父类中的方法
  1. 抽象类的子类:
      1. 要么重写方法抽象类中的所有抽象方法。
      2. 要么就让子类自己变成抽象类

在这里插入图片描述

三、接口

接口:体现的思想是对规则的声明,Java中的接口更多体现的是对行为的抽象(抽象方法)

  • 思路:

如果发现一个类,所有的组成,都是抽象方法

    • 不能有成员变量
    • 不能有普通的方法
  • 这种类,我们就会将他设计为Java中的接口,因为现在这个类存在的唯一价值,就是声明规则。给需要的接口的使用者命名规则。
3.1 接口的定义格式

和定义类很像:

interface 接口名 {
    
    }

注意:接口不允许实例化。

接口和类之间是实现关系,通过implements关键字来完成接口的实现(和继承父级一样的写法)

class 类名 implements 接口名 {
    
    }

实现类 (也就是接口的子类)

  1. 要么重写接口中的所有抽象方法。
  2. 要么将实现类变成抽象类(继承后的抽象方法就必须存活在抽象类中)

第一种使用接口的方式(实现类中,重写抽象方法)

/**
 * 定义一个接口
 */
interface Inter {
    
    
    public void method ();

    public void show ();
}

// 第一中使用接口的方法,使用接口(实现类)
class demoClass implements Inter {
    
    
    // 1. 要么将接口里面的规则(抽象方法)全部重写
    public void method() {
    
    
        System.out.println("我是实现类中的 method方法");
    }

    public void show () {
    
    
        System.out.println("我是实现类中的 show方法");
    }
}

第二种使用接口的方式(将实现类变成抽象类) 不推荐使用

/**
 * 定义一个接口
 */
interface Inter {
    
    
    public void method ();

    public void show ();
}

// 接口的第二种使用方法(变成抽象类,让其他类继承我的实现类)
abstract class Demo implements Inter {
    
    
    // 要么将这个实现类变成抽象类
}

class Test extends Demo {
    
    
    public void method () {
    
    

    }

    public void show () {
    
    

    }
}
3.2 接口成员特点
  1. 成员变量: 只能定义常量,因为系统会默认加上三个关键字:
    • public static final
    • 这三个关键字没有顺序关系
  • 所以接口定义的时候,遵循static 和 final的使用规则。
  1. 成员方法:只能是抽象方法,因为系统会默认加入两个关键字

    • public abstract
  2. 接口中没有构造方法

3.3 类和接口的关系

在这里插入图片描述

1、 类和类之间的关系只能单继承,或者多层继承(前面有讲过),这里展示一个类继承多个类:

package com.liujintao.demo;


public class InterfaceDemo02 {
    
    
    public static void main(String[] LiuJinTao) {
    
    

    }
}


// 定义一个抽象父类
abstract class Fu1 {
    
    
    // 抽象方法
    public abstract void show();
}

// 定义第二个抽象父类
abstract class Fu2 {
    
    
    public abstract void show();
}

// 定义一个子类继承抽象方法 (类与类不支持一个继承多个)
abstract class Zi extends Fu1, Fu2 {
    
     // 报错 同时继承了两个类
    // 重写抽象方法
    public  void show() {
    
    

    }
}

2、 类和接口之间的关系(这里展示一个继承多个的代码实现):

package com.liujintao.demo;

public class InterfaceDemo02 {
    
    
    public static void main(String[] LiuJinTao) {
    
    

    }
}

// 定义一个接口
interface Interf {
    
    
    public void show ();
    public void method();
}


// 定义第二个接口
interface Interf2 {
    
    
    public void show ();
    public void method ();
}

// 定义一个实现类(一个类继承多个接口(类))

abstract class testClass implements Interf, Interf2 {
    
    
    // 实现了接口(就相当于继承了),里面全是抽象方法,因此必须存活在抽象类中。
    public void show () {
    
    
        System.out.println("我是实现类,实现接口继承方法后,重写抽象类");
    }

    public void method () {
    
    
        System.out.println("我是实现类,实现了接口的继承方法后,重写抽象类");
    }
}
  • 这里主要看我实现类以及里面对抽象方法的重写。

3、 接口和接口之间的关系(和上面一样,一个接口继承多个接口代码展示):

package com.liujintao.demo;

public class InterfaceDemo02 {
    
    
    public static void main(String[] LiuJinTao) {
    
    
    }
}

// 定义第一个接口
interface isInter1 {
    
    
    public void showA();
}

// 定义第二个接口
interface isInter2 {
    
    
    public void showB();
}


// 定义第三个接口,实现上面连个接口的继承
interface  Come extends isInter1, isInter2 {
    
    
    public void showA();
    public void showB();
}


  • 一个接口使用继承的方式继承多个接口,如果下次有个实现类,就得重写这些接口里面的所有抽象方法。
3.4 接口和抽象类的对比
  • 抽象类:对事物做抽象(描述事物)
  • 接口:对行为抽象(制定规则)

接口里面写的全是抽象的方法,然后通过实现类对我的规则进行重写,完成功能的实现。

四、多态

在这里插入图片描述

4.1 多态的前提条件
  • 有继承/接口实现关系
  • 有方法重写
  • 父类引用指向子类对象

多态分为:

  • 对象多态
  • 行为多态
4.2 对象多态
  • 父类的引用指向了子类的对象
package com.liujintao.polymorphic;

public class PolymorphicDemo {
    
    
    public static void main(String[] LiuJinTao){
    
    
        // 对象多态的实现
        Animal x = new Dog();
        Animal y = new Cat();

    }
}

// 定义一个父类
class Animal {
    
    

}

// 下面定义两个子类
class Dog extends Animal {
    
    

}

class Cat extends Animal {
    
    

}

对象多态的好处:

  • 方法的形参定义为父类类型,这个方法就可以接受到该父类的任意子类对象了。
package com.liujintao.polymorphic;

public class PolymorphicDemo {
    
    
    public static void main(String[] LiuJinTao){
    
    
        // 对象多态的实现
        Animal x = new Dog();
        Animal y = new Cat();

        // 调用方法 传递子类对象给父类引用
        userAnimal(new Dog());
        userAnimal(new Cat());

    }


    // 展示一下对象多态的好处 (就是定义一个父类的实例,接受子类对象)
    public static void  userAnimal (Animal element) {
    
    

    }
}

// 定义一个父类
class Animal {
    
    

}

// 下面定义两个子类
class Dog extends Animal {
    
    

}

class Cat extends Animal {
    
    

}

4.2 行为多态:
package com.liujintao.polymorphic;

import java.sql.SQLOutput;

public class PolymorphicDemo {
    
    
    public static void main(String[] LiuJinTao){
    
    


        // 调用方法 传递子类对象给父类引用
//        userAnimal(new Dog());
        userAnimal(new Cat());

    }


    // 展示一下对象多态的好处 (就是定义一个父类的实例,接受子类对象)
    public static void  userAnimal (Animal element) {
    
    
        // 行为多态的使用
        element.eat();      // cat
    }
}

// 定义一个父类
abstract class Animal {
    
    
    public abstract void eat ();
}

// 下面定义两个子类
class Dog extends Animal {
    
    
    public void eat () {
    
    
        System.out.println("dog");
    }
}

class Cat extends Animal {
    
    
    public void eat () {
    
    
        System.out.println("cat");
    }
}

userAnimal(new Cat()); : 根据传递的子类对象,方法的形参引用不同的对象,实现功能方法。

4.3 多态的成员访问特点
  1. 成员变量:编译看左边(父类), 运行看左边(父类)

  2. 成员方法:编译看左边(父类), 运行看右边(子类)

    • 在编译的时候,会检查父类中有没有这个方法:
      • 没有:编译报错
      • 有:编译通过,但是运行的时候,一定会执行子类的方法逻辑
        • 因为担心父类的方法里面没有逻辑,是一个抽象方法。
  3. 多态创建对象,调用静态成员:

    • 静态的成员,推荐类名进行调用
    • 细节:静态的成员,可以使用对象名调用,但这是一种假象。
      • 生成字节码文件后,会自动将对象名调用,改成类名调用(也就是会说执行的时候就已经是类名调用了)
  • 1、访问成员变量的时候,访问的是父类,如果将变量设计在了本类,那就是本类的变量值。
package com.liujintao.polymorphic;

public class polymorphicDemo02 {
    
    
    public static void main(String[] args) {
    
    
        Zi z = new Zi();
        System.out.println(z.num);  // 100
    }
}

// 定义一个父类
class Fu {
    
    
    int num = 100;
    public void method () {
    
    
        System.out.println(num);
    }
}


// 定义一个子类
class Zi extends Fu {
    
    
    public void method () {
    
    
        System.out.println(num);
    }
}

  • 2、访问成员方法的时候
package com.liujintao.polymorphic;

public class polymorphicDemo02 {
    
    
    public static void main(String[] args) {
    
    
        Zi z = new Zi();
        System.out.println(z.num);  // 100
        z.method();                 // 我是子类
    }
}

// 定义一个父类
class Fu {
    
    
    int num = 100;
    public void method () {
    
    
        System.out.println(num);
    }
}


// 定义一个子类
class Zi extends Fu {
    
    
    public void method () {
    
    
        System.out.println(num);
        System.out.println("我是子类");
    }
}

  • 3、访问的是父类
Zi z = new Zi();

 Zi.print();  // <== z.print(); 编译的时候自动改为类调用。

// 定义一个父类
class Fu {
    
    

    public static void print() {
    
    
        System.out.println("父类----print");
    }
}


// 定义一个子类
class Zi extends Fu {
    
    
    public static void print() {
    
    
        System.out.println("父类----print");
    }
}
  • 总而言之,多态的访问,必须符合多态的形式
  • 父类没有的,子类有的就访问不了,(这就是多态的弊端),解决方法就得用转型技术。往下面看。
4.4 多态的转型技术

向上转型:

  • 从子到父 (父类引用指向子类对象)
  • Fu f = new Zi();

向下转型:

  • 从父到子(将父类引用所指向的对象,转交给子类类型)
  • Zi z = (Zi)f;
4.5 多态中的转型问题
  • 关键字 instanceof
  • 使用格式:
    • 对象名 instanceof 类型
    • 判断一个对象是否是一个类的实例
    • (通俗易懂的理解:判断关键字左边的对象,是否是右边的类型,返回值为boolean类型)就是判断数据类型是否相同

在这里插入图片描述

五、综合练习:

在这里插入图片描述

测试类:

package com.liujintao.test;


import com.liujintao.polymorphic.PolymorphicDemo03;

import java.util.Scanner;

public class Test {
    
    
    public static void main(String[] args) {
    
    
        Scanner sc = new Scanner(System.in);
        System.out.println("请选择支付方式:  1. 支付平台支付   2. 银行卡网银支付  3. 信用卡快捷支付");
        int choice = sc.nextInt();

        // 定义一个接口类型的引用
        Payment payment = null;

        switch (choice) {
    
    
            case 1 :
                // 父类引用指向子类对象
                payment = new PlatformPaymentImpl();
                break;
            case 2:
                payment = new BankcardPaymentImpl();
                break;
            case 3:
                payment = new CreditCardsAccepted();
        }

        System.out.println("请输入您的支付金额: ");
        double money = sc.nextDouble();
        // 通过实现类对象。访问实现类里面的方法
        payment.pay(money);
    }
}

先定义一个接口:

package com.liujintao.test;

/**
 * 支付接口
 */
public interface Payment {
    
    
    void pay(double money);
}

第一个实现类:

package com.liujintao.test;

/**
 * 实现类
 */
public class PlatformPaymentImpl implements Payment {
    
    
    /**
     * 重写接口方法
     * @param money
     */
    @Override
    public void pay(double money) {
    
    
        System.out.println("通过支付平台支付了:" + money + "元!");
    }
}

第二个实现类:

package com.liujintao.test;

/**
 * 实现类
 */

public class BankcardPaymentImpl implements Payment{
    
    
    @Override
    public void pay(double money) {
    
    
        System.out.println("通过银行卡网银支付了:" + money + "元!");
    }
}

第三个实现类:

package com.liujintao.test;

/**
 * 实现类
 */
public class CreditCardsAccepted implements Payment {
    
    
    public void pay(double money) {
    
    
        System.out.println("通过信用卡支付了:" + money + "元");
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Forever_Hopeful/article/details/134632152