Loading

多态-抽象类-接口


返回 我的技术栈(Technology Stack)



多态(polymorphic)


  • 多态的前提:

    • 要有继承关系
    • 要有方法重写
    • 要有父类引用指向子类对象
  • 成员变量:编译看左边(父类);运行看左边(父类)

  • 成员方法:编译看左边(父类);运行看右边(子类)----即动态绑定:先看父类是否有该成员方法,通过编译,再执行子类的成员方法

  • 静态方法:编译看左边(父类);运行看左边(父类)

  • 注意:静态和类相关,算不上重写,所以,访问还是左边的。只有非静态的成员方法,编译看左边,运行看右边

    class Test {
    public static void main(String[] args) {
    Fu f = new Zi(); //父类引用指向子类对象——向上转型 Zi hai = (Zi)f;——向下转型
    //f.method(); 运行报错! //成员方法编译看左边,运行看右边。
    //即先看父类中是否有该方法,通过了再执行子类,若子类没有该方法,就执行父类的方法(因为继承)
    f.show();
    }
    }

    class Fu {
    public void show() {
    System.out.println("fu show");
    }
    }

    class Zi extends Fu {
    public void show() {
    System.out.println("zi show");
    }

    public void method() {
    System.out.println("zi method");
    }
    }

    运行结果:zi show

    上转型:只能执行被子类所重写过的方法和被子类继承的方法
    Animal mydog = new Dog();
    把mydog当成Animal;父类使用子类中的方法。

抽象类的概述及特点


  • 抽查类的特点:
    • 抽象类和抽象方法必须用abstract关键字修饰
    • 如:abstract class 类名 {}
    • public abstract void eat ();
  • 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口。抽象方法在抽象类中,父类中的抽象方法强制子类重写
  • 抽象类不能被实例化
  • 抽象类的子类:
    • 要么是抽象类

    • 要么重写抽象类中的所有抽象方法

      抽象类的猫狗案例
      class Test_Animal {
      public static void main(String[] args) {
      Cat c = new Cat("加菲",8);
      System.out.println(c.getName() + "------" + c.getAge());
      c.eat();
      c.catchMouse();

      Dog d = new Dog("八公",30);
      System.out.println(d.getName() + "------" + d.getAge());
      d.eat();
      d.lookHome();
      }
      }

      abstract class Animal {
      private String name; //姓名
      private int age; //年龄

      public Animal() {} //无参构造
      public Animal(String name,int age) {
      this.name = name;
      this.age = age;
      }

      public void setName(String name) { //设置姓名
      this.name = name;
      }
      public String getName() { //获取姓名
      return name;
      }

      public void setAge(int age) { //设置年龄
      this.age = age;
      }
      public int getAge() { //获取年龄
      return age;
      }

      public abstract void eat(); //吃饭的抽象方法
      }

      class Cat extends Animal {
      public Cat() {} //空参构造
      public Cat(String name,int age) { //有参构造
      super(name,age);
      }

      public void eat() { //抽象类中含有抽象方法,子类必须重写该方法
      System.out.println("猫吃鱼");
      }

      public void catchMouse() {
      System.out.println("抓老鼠");
      }
      }

      class Dog extends Animal {
      public Dog() {} //无参构造
      public Dog(String name,int age) { //有参构造
      super(name,age);
      }

      public void eat() { //抽象类中含有抽象方法,子类必须重写该方法
      System.out.println("狗吃肉");
      }

      public void lookHome() {
      System.out.println("看家门");
      }
      }

      输出结果:加菲------8
      猫吃鱼
      抓老鼠
      八公------30
      狗吃肉
      看家门

      /********************************************************/

      抽象类练习员工案例
      class Test_Employee {
      public static void main(String[] args) {
      Coder c = new Coder("德玛西亚","007",8000);
      c.work();

      Manager m = new Manager("赵老师","9527",3000,20000);
      m.work();
      }
      }

      abstract class Employee {
      private String name; //姓名
      private String id; //工号
      private double salary; //薪水

      public Employee() {} //无参构造
      public Employee(String name,String id,double salary) { //有参构造
      this.name = name;
      this.id = id;
      this.salary = salary;
      }

      public void setName(String name) { //设置姓名
      this.name = name;
      }
      public String getName() { //获取姓名
      return name;
      }

      public void setId(String id) { //设置工号
      this.id = id;
      }
      public String getId() { //获取工号
      return id;
      }

      public void setSalary(double salary) { //设置薪水
      this.salary = salary;
      }
      public double getSalary() { //获取薪水
      return salary;
      }

      public abstract void work(); //抽象的工作方法
      }

      //程序员
      class Coder extends Employee {
      public Coder() {} //无参构造
      public Coder(String name,String id,double salary) { //有参构造
      super(name,id,salary);
      }

      public void work() {
      System.out.println("我的姓名是:" + this.getName() + ",我的工号是:" + this.getId() +
      ",我的工资是:" + this.getSalary() + ",我的工作内容是敲代码");
      }
      }

      //项目经理
      class Manager extends Employee {
      private int bonus; //奖金

      public Manager() {} //无参构造
      public Manager(String name,String id,double salary,int bonus) { //有参构造
      super(name,id,salary);
      this.bonus = bonus;
      }

      public void work() {
      System.out.println("我的姓名是:" + this.getName() + ",我的工号是:" + this.getId() +
      ",我的工资是:" + this.getSalary() + ",我的奖金是:" + bonus + ",我的工作内容是管理");
      }
      }

      //我的姓名是:德玛西亚,我的工号是:007,我的工资是:8000.0,我的工作内容是敲代码
      我的姓名是:赵老师,我的工号是:9527,我的工资是:3000.0,我的奖金是:20000,我的工作内容是管理

抽象类中的面试题


1、一个抽象类如果没有抽象方法,可不可以定义为抽象类?有什么意义?
答案:可以。这么做的目的只有一个,就是不让其他类创建本类对象,交给子类完成
2、abstract不能喝哪些关键字共存?
答案:static 理由:被abstract修饰的方法没有方法体
被static修饰的可以用“类名.”调用,但是“类名.”调用抽象方法是没有意义的
final 理由:被abstract修饰的方法强制子类重写
被final修饰的不让子类重写,所以他俩是矛盾的
private 理由:被abstract修饰的是为了让子类看到并强制重写
被private修饰不让子类访问,所以他俩是矛盾的

接口的概述及其特点


  • 概念:

    • 狭义上就是指Java中的interface
    • 广义上就是对外提供规则的都是接口
    • 例如:
      • //注意接口不能被实例化,在接口中定义的变量,都是常量(类似被final修饰)

      • //接口中没有构造方法;接口中不能定义非抽象方法

        interface Inter {
        public abstract void print(); //接口中的方法是抽象的
        }
        class Demo implements Inter { //类实现接口用implements
        public void print() {
        System.out.println("文本");
        }
        }

  • 接口的子类:

    • 可以是抽象类。但是意义不大。
    • 可以是具体类。要重写接口中的所有抽象方法(推荐方案)
  • 接口的成员特点

    • 成员变量:只能是常量,并且是静态的并非公共的。
      • 比如:

        class Demo_Interface {
        public static void main(Strings[] args) {
        Demo d = new Demo();
        d.print();

        System.out.println(Inter.num); //不报错,匿名调用,说明是静态
        }
        }

        interface Inter {
        //对上方的解释:隐藏了修饰符 public static
        int num = 10;
        //对下方的解释:接口的变量中隐藏了final关键字 final int num = 10;变成了最终常量

        /总结两者:接口成员变量默认的修饰符:public static final
        建议自己手动给出 public static final int num =10;
        /

        /public Inter() {} 运行报错! 接口中没有构造方法
        接口相当于干爹,Demo类访问的是object类中的构造方法
        /

        /*public void print() {} 运行报错! 接口中不能定义非抽象方法 */

        public abstract void print(); //成员方法只能是抽象方法
        //默认修饰符:public abstract 建议自己手动给出

        }

        class Demo implements Inter { //一个类不写继承任何类,默认继承object类
        // 即相当于 class Demo extends object implements Inter{}

        public void print() {
        // num = 20; 报错! //final int num = 10;变成了最终常量,不能被修改
        System.out.println(num);
        }

        }

        运行结果:10
        10

类与类,类与接口,接口与接口的关系


  • 1、类与类:
    • 继承关系,只能单继承,也可以多层继承——如:class Person extends Teacher
  • 2、类与接口:
    • 实现关系,可以单实现,也可以多实现——如:class Demo implements InterA,InterB {}
    • 并且还可以在继承一个类的同时实现多个接口——如:class Demo extends object implements InterA,InterB {}
  • 3、接口与接口:
    • 继承关系,可以单继承,也可以多继承——如:interface InterC extends InterB,InterA{}

抽象类和接口的关系:


A:成员区别
1、抽象类:
(1)成员变量:可以变量,也可以常量
(2)构造方法:有
(3)成员方法:可以抽象,也可以非抽象
2、接口:
(1)成员变量:只可以常量
(2)成员方法:只可以抽象
B:关系区别
1、类与类:继承,单继承
2、类与接口:实现,单实现,多实现
3、接口与接口:继承,单继承,多继承
C:设计理念区别
1、抽象类 被继承体现的是:“is a”的关系。抽象类中定义的是该继承体系的共性功能
2、接口 被实现体现的是:“like a”的关系。接口中定义的是该继承体系的扩展功能


猫狗案例演示


动物类:姓名,年龄,吃饭,睡觉
猫和狗
动物培训接口:跳高

class Demo_Animal {
public static void main(String[] args) {
Cat c = new Cat("加菲",8);
c.eat();
c.sleep();

JumpCat jc= new JumpCat("跳高猫",3);
jc.eat();
jc.sleep();
jc.jump();
}
}

abstract class Animal {
private String name; //姓名
private int age; //年龄

public Animal() {} //无参构造
public Animal(String name,int age) { //有参构造
this.name = name;
this.age = age;
}

public void setName(String name) { //设置姓名
this.name = name;
}
public String getName() { //获取姓名
return name;
}

public void setAge(int age) { // 设置年龄
this.age = age;
}
public int getAge() { //获取年龄
return age;
}

public abstract void eat(); //吃饭的抽象方法
public abstract void sleep(); //睡觉的抽象方法
//抽象方法要在抽象类中!

}

interface Jumping { //跳高的接口
public abstract void jump();
}

class Cat extends Animal {
public Cat() {} //无参构造
public Cat(String name,int age) { //有参构造
super(name,age);
}

public void eat() {
System.out.println("猫吃鱼");
}

public void sleep() {
System.out.println("侧着睡");
}
}

class JumpCat extends Cat implements Jumping {
public JumpCat() {} //无参构造
public JumpCat(String name,int age) { //有参构造
super(name,age);
}

public void jump() {
System.out.println("猫跳高");
}
}

输出结果:猫吃鱼
侧着睡
猫吃鱼
侧着睡
猫跳高


总结:
抽象类:只有普通方法和抽象方法。
接口:只有全局常量和抽象方法。没有普通方法


posted @ 2021-03-27 23:22  言非  阅读(93)  评论(0)    收藏  举报