博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaSE学习笔记(八)—— 多态&抽象类&接口
阅读量:4680 次
发布时间:2019-06-09

本文共 29794 字,大约阅读时间需要 99 分钟。

一、多态

1.1 多态概述

  多态是指,同一个对象(事物),在不同时刻体现出来的不同状态。

  举例::

  猫可以是猫的类型。猫 m = new 猫();

  同时猫也是动物的一种,也可以把猫称为动物。动物 d = new 猫();

  再举一个例子:

  水在不同时刻的状态:液体,固体,气态

1.2 多态的前提

  1. 要有继承关系。
  2. 要有方法重写。
    其实没有也是可以的,但是如果没有这个就没有意义。    动物 d = new 猫();    d.show();    动物 d = new 狗();    d.show();
  3. 要有父类引用指向子类对象。
    父 f =  new 子();

1.3 多态中的成员访问特点

  • 成员变量
    编译看左边,运行看左边。
  • 构造方法

    创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
  • 成员方法

    编译看左边,运行看右边。
  • 静态方法

    编译看左边,运行看左边。(静态和类相关,算不上重写,所以,访问还是左边的)

  注:由于成员方法存在方法重写,所以它运行看右边。

class Fu {    public int num = 100;    public void show() {        System.out.println("show Fu");    }        public static void function() {        System.out.println("function Fu");    }}class Zi extends Fu {    public int num = 1000;    public int num2 = 200;    public void show() {        System.out.println("show Zi");    }        public void method() {        System.out.println("method zi");    }        public static void function() {        System.out.println("function Zi");    }}class DuoTaiDemo {    public static void main(String[] args) {        //要有父类引用指向子类对象。        //父 f =  new 子();        Fu f = new Zi();        System.out.println(f.num);//100        //找不到符号        //System.out.println(f.num2);                f.show();//show Zi        //找不到符号        //f.method();        f.function();//function Fu    }}

【内存图解】

1.4 多态的好处和弊端

【多态的好处】

  1. 提高了代码的维护性(继承保证)
  2. 提高了代码的扩展性(由多态保证)
class Animal {    public void eat(){        System.out.println("eat");    }        public void sleep(){        System.out.println("sleep");    }}class Dog extends Animal {    public void eat(){        System.out.println("狗吃肉");    }        public void sleep(){        System.out.println("狗站着睡觉");    }}class Cat extends Animal {    public void eat() {        System.out.println("猫吃鱼");    }        public void sleep() {        System.out.println("猫趴着睡觉");    }}class Pig extends Animal {    public void eat() {        System.out.println("猪吃白菜");    }        public void sleep() {        System.out.println("猪侧着睡");    }}//针对动物操作的工具类class AnimalTool {    private AnimalTool(){}    /*    //调用猫的功能    public static void useCat(Cat c) {        c.eat();        c.sleep();    }        //调用狗的功能    public static void useDog(Dog d) {        d.eat();        d.sleep();    }        //调用猪的功能    public static void usePig(Pig p) {        p.eat();        p.sleep();    }    */    public static void useAnimal(Animal a) {        a.eat();        a.sleep();    }    }class DuoTaiDemo2 {    public static void main(String[] args) {        //我喜欢猫,就养了一只        Cat c = new Cat();        c.eat();        c.sleep();                //我很喜欢猫,所以,又养了一只        Cat c2 = new Cat();        c2.eat();        c2.sleep();                //我特别喜欢猫,又养了一只        Cat c3 = new Cat();        c3.eat();        c3.sleep();        //...        System.out.println("--------------");        //问题来了,我养了很多只猫,每次创建对象是可以接受的        //但是呢?调用方法,你不觉得很相似吗?仅仅是对象名不一样。        //我们准备用方法改进        //调用方式改进版本        //useCat(c);        //useCat(c2);        //useCat(c3);                //AnimalTool.useCat(c);        //AnimalTool.useCat(c2);        //AnimalTool.useCat(c3);                AnimalTool.useAnimal(c);        AnimalTool.useAnimal(c2);        AnimalTool.useAnimal(c3);        System.out.println("--------------");                //我喜欢狗        Dog d = new Dog();        Dog d2 = new Dog();        Dog d3 = new Dog();        //AnimalTool.useDog(d);        //AnimalTool.useDog(d2);        //AnimalTool.useDog(d3);        AnimalTool.useAnimal(d);        AnimalTool.useAnimal(d2);        AnimalTool.useAnimal(d3);        System.out.println("--------------");                //我喜欢宠物猪        //定义一个猪类,它要继承自动物,提供两个方法,并且还得在工具类中添加该类方法调用        Pig p = new Pig();        Pig p2 = new Pig();        Pig p3 = new Pig();        //AnimalTool.usePig(p);        //AnimalTool.usePig(p2);        //AnimalTool.usePig(p3);        AnimalTool.useAnimal(p);        AnimalTool.useAnimal(p2);        AnimalTool.useAnimal(p3);        System.out.println("--------------");                //我喜欢宠物狼,老虎,豹子...        //定义对应的类,继承自动物,提供对应的方法重写,并在工具类添加方法调用        //前面几个必须写,我是没有意见的        //但是,工具类每次都改,麻烦不        //我就想,你能不能不改了        //太简单:把所有的动物都写上。问题是名字是什么呢?到底哪些需要被加入呢?        //改用另一种解决方案。            }        /*    //调用猫的功能    public static void useCat(Cat c) {        c.eat();        c.sleep();    }        //调用狗的功能    public static void useDog(Dog d) {        d.eat();        d.sleep();    }    */}

【多态的弊端】

  不能使用子类的特有功能。

class Fu {    public void show() {        System.out.println("show fu");    }}class Zi extends Fu {    public void show() {        System.out.println("show zi");    }        public void method() {        System.out.println("method zi");    }}class DuoTaiDemo3 {    public static void main(String[] args) {        //测试        Fu f = new Zi();        f.show();        //f.method();//报错    }}

  我就想使用子类的特有功能?行不行?行。

  怎么用呢?

  A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)

  B:把父类的引用强制转换为子类的引用。(向下转型)

1.5 多态中的转型问题

【向上转型】

  从子到父

  父类引用指向子类对象

【向下转型】

  从父到子

  父类引用转为子类对象

class Fu {    public void show() {        System.out.println("show fu");    }}class Zi extends Fu {    public void show() {        System.out.println("show zi");    }        public void method() {        System.out.println("method zi");    }}class DuoTaiDemo4 {    public static void main(String[] args) {        //测试        //向上转型        Fu f = new Zi();        f.show();//show zi        //f.method();                //创建子类对象        //Zi z = new Zi();        //z.show();        //z.method();                //你能够把子的对象赋值给父亲,那么我能不能把父的引用赋值给子的引用呢?        //向下转型        Zi z = (Zi)f;//要求该f必须是能够转换为Zi的。        z.show();//show zi        z.method();//method zi    }}

  注意:在多态的向下转型中容易出现ClassCastException——类型转换异常

class Animal {    public void eat(){}}class Dog extends Animal {    public void eat() {}        public void lookDoor() {        }}class Cat extends Animal {    public void eat() {        }        public void playGame() {            }}class AnimalDemo {    public static void main(String[] args) {        //内存中的是狗        Animal a = new Dog();        a.eat();        //a.lookDoor();//报错                Dog d = (Dog)a;        d.eat();        d.lookDoor();                //内存中是猫        a = new Cat();        a.eat();        //a.playGame();//报错                Cat c = (Cat)a;        c.eat();        c.playGame();                //内存中是猫        Dog dd = (Dog)a; //ClassCastException    }}

1.6 多态的成员访问特点及转型的理解

class 孔子爹 {    public int age = 40;        public void teach() {        System.out.println("讲解JavaSE");    }}class 孔子 extends 孔子爹 {    public int age = 20;        public void teach() {        System.out.println("讲解论语");    }        public void playGame() {        System.out.println("英雄联盟");    }}

  Java培训特别火,很多人来请孔子爹去讲课,这一天孔子爹被请走了,但是还有人来请,就剩孔子在家,价格还挺高。孔子一想,我是不是可以考虑去呢?然后就穿上爹的衣服,带上爹的眼睛,粘上爹的胡子。就开始装爹。

//向上转型孔子爹 k爹 = new 孔子();//到人家那里去了System.out.println(k爹.age); //40k爹.teach(); //讲解论语//k爹.playGame(); //这是儿子才能做的

  讲完了,下班回家了。脱下爹的装备,换上自己的装备

//向下转型孔子 k = (孔子) k爹; System.out.println(k.age); //20k.teach(); //讲解论语k.playGame(); //英雄联盟

1.7 多态练习

【猫狗案例】

class Animal {    public void eat(){        System.out.println("吃饭");    }}class Dog extends Animal {    public void eat() {        System.out.println("狗吃肉");    }        public void lookDoor() {        System.out.println("狗看门");    }}class Cat extends Animal {    public void eat() {        System.out.println("猫吃鱼");    }        public void playGame() {        System.out.println("猫捉迷藏");    }}class DuoTaiTest {    public static void main(String[] args) {        //定义为狗        Animal a = new Dog();        a.eat();        System.out.println("--------------");        //还原成狗        Dog d = (Dog)a;        d.eat();        d.lookDoor();        System.out.println("--------------");        //变成猫        a = new Cat();        a.eat();        System.out.println("--------------");        //还原成猫        Cat c = (Cat)a;        c.eat();        c.playGame();        System.out.println("--------------");                //演示错误的内容        //Dog dd = new Animal();        //Dog ddd = new Cat();        //ClassCastException        //Dog dd = (Dog)a;    }}

【看程序写结果】

class A {    public void show() {        show2();    }    public void show2() {        System.out.println("我");    }}class B extends A {    /*    public void show() {        show2();    }    */    public void show2() {        System.out.println("爱");    }}class C extends B {    public void show() {        super.show();    }    public void show2() {        System.out.println("你");    }}public class DuoTaiTest4 {    public static void main(String[] args) {        A a = new B();        a.show();//爱                B b = new C();        b.show();//你    }}

继承的时候:

  子类中有和父类中一样的方法,叫重写。

  子类中没有父亲中出现过的方法,方法就被继承过来了。

二、抽象类

2.1 抽象类概述

  回想前面我们的猫狗案例,提取出了一个动物类。并且我们在前面也创建过了动物对象,其实这是不对的。为什么呢?因为,我说动物,你知道我说的是什么动物吗?只有看到了具体的动物,你才知道,这是什么动物。 所以说,动物本身并不是一个具体的事物,而是一个抽象的事物。只有真正的猫,狗才是具体的动物。同理,我们也可以推想,不同的动物吃的东西应该是不一样的,所以,我们不应该在动物类中给出具体体现,而是应该给出一个声明即可。在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。

2.2 抽象类的特点

  1. 抽象类和抽象方法必须用abstract关键字修饰
    格式abstract class 类名 {}public abstract void eat();
  2. 抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类
  3. 抽象类不能实例化
    因为它不是具体的。那么,抽象类如何实例化呢?按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。Animal a = new Cat();抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢?用于子类访问父类数据的初始化
  4. 抽象的子类
    a:如果不想重写抽象方法,该子类是一个抽象类。b:重写所有的抽象方法,这个时候子类是一个具体的类。

  演示案例:

abstract class Animal {    //抽象方法    //public abstract void eat(){} //空方法体,这个会报错。抽象方法不能有主体    public abstract void eat();        public Animal(){}}//子类是抽象类abstract class Dog extends Animal {}//子类是具体类,重写抽象方法class Cat extends Animal {    public void eat() {        System.out.println("猫吃鱼");    }}class AbstractDemo {    public static void main(String[] args) {        //创建对象        //Animal是抽象的; 无法实例化        //Animal a = new Animal();        //通过多态的方式        Animal a = new Cat();        a.eat();    }}

2.3 抽象类的成员特点

【成员变量】

  既可以是变量,也可以是常量。

【构造方法】

  有构造方法,但是不能实例化。那么,构造方法的作用是什么呢?

  用于子类访问父类数据的初始化

【成员方法】

  可以有抽象方法:限定子类必须完成某些动作。

  也可以有非抽象方法:子类继承的事情,提高代码复用性。

abstract class Animal {    public int num = 10;    public final int num2 = 20;    public Animal() {}        public Animal(String name,int age){}        public abstract void show();        public void method() {        System.out.println("method");    }}class Dog extends Animal {    public void show() {        System.out.println("show Dog");    }}class AbstractDemo2 {    public static void main(String[] args) {        //创建对象        Animal a = new Dog();        a.num = 100;        System.out.println(a.num);//100        //a.num2 = 200;        System.out.println(a.num2);//20        System.out.println("--------------");        a.show();//show Dog        a.method();//method    }}

2.4 抽象类练习

【猫狗案例】

  具体事物:猫,狗

  共性:姓名,年龄,吃饭

/*    分析:从具体到抽象        猫:            成员变量:姓名,年龄            构造方法:无参,带参            成员方法:吃饭(猫吃鱼)                    狗:            成员变量:姓名,年龄            构造方法:无参,带参            成员方法:吃饭(狗吃肉)                    因为有共性的内容,所以就提取了一个父类。动物。        但是又由于吃饭的内容不一样,所以吃饭的方法是抽象的,        而方法是抽象的类,类就必须定义为抽象类。                抽象动物类:            成员变量:姓名,年龄            构造方法:无参,带参            成员方法:吃饭();        实现:从抽象到具体        动物类:            成员变量:姓名,年龄            构造方法:无参,带参            成员方法:吃饭();                    狗类:            继承自动物类            重写吃饭();                    猫类:            继承自动物类            重写吃饭();*///定义抽象的动物类abstract class Animal {    //姓名    private String name;    //年龄    private int age;        public Animal() {}        public Animal(String name,int age) {        this.name = name;        this.age = age;    }        public String getName() {        return name;    }        public void setName(String name) {        this.name = name;    }        public int getAge() {        return age;    }        public void setAge(int age) {        this.age = age;    }        //定义一个抽象方法    public abstract void eat();}//定义具体的狗类class Dog extends Animal {    public Dog() {}        public Dog(String name,int age) {        super(name,age);    }        public void eat() {        System.out.println("狗吃肉");    }}//定义具体的猫类class Cat extends Animal {    public Cat() {}        public Cat(String name,int age) {        super(name,age);    }        public void eat() {        System.out.println("猫吃鱼");    }}//测试类class AbstractTest {    public static void main(String[] args) {        //测试狗类        //具体类用法        //方式1:        Dog d = new Dog();        d.setName("旺财");        d.setAge(3);        System.out.println(d.getName()+"---"+d.getAge());        d.eat();        //方式2:        Dog d2 = new Dog("旺财",3);        System.out.println(d2.getName()+"---"+d2.getAge());        d2.eat();        System.out.println("---------------------------");                Animal a = new Dog();        a.setName("旺财");        a.setAge(3);        System.out.println(a.getName()+"---"+a.getAge());        a.eat();                Animal a2 = new Dog("旺财",3);        System.out.println(a2.getName()+"---"+a2.getAge());        a2.eat();    }}

【学生案例】

  具体事务:基础班学员,就业班学员

  共性:姓名,年龄,班级,学习,吃饭

/*    分析:        基础班学员            成员变量:姓名,年龄,班级            成员方法:学习,吃饭        就业班学员            成员变量:姓名,年龄,班级            成员方法:学习,吃饭                    得到一个学员类。            成员变量:姓名,年龄,班级            成员方法:学习,吃饭                实现:        学员类        基础班学员        就业班学员*///定义抽象学员类abstract class Student {    //姓名    private String name;    //年龄    private int age;    //班级    private String grand;        public Student() {}        public Student(String name,int age,String grand) {        this.name = name;        this.age = age;        this.grand = grand;    }        public String getName() {        return name;    }        public void setName(String name) {        this.name = name;    }        public int getAge() {        return age;    }        public void setAge(int age) {        this.age = age;    }        public String getGrand() {        return grand;    }        public void setGrand(String grand) {        this.grand = grand;    }        //学习    public abstract void study();        //吃饭    public void eat() {        System.out.println("学习累了,就该吃饭");    }}//具体基础班学员类class BasicStudent extends Student {    public BasicStudent() {}        public BasicStudent(String name,int age,String grand) {        super(name,age,grand);    }        public void study() {        System.out.println("基础班学员学习的是JavaSE");    }}//具体就业班学员类class WorkStudent extends Student {    public WorkStudent() {}        public WorkStudent(String name,int age,String grand) {        super(name,age,grand);    }        public void study() {        System.out.println("就业班学员学习的是JavaEE");    }}class AbstractTest3 {    public static void main(String[] args) {        //我仅仅测试基础班学员        //按照多态的方式测试        Student s = new BasicStudent();        s.setName("林青霞");        s.setAge(27);        s.setGrand("1111");        System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getGrand());        s.study();        s.eat();        System.out.println("--------------");                s = new BasicStudent("武鑫",48,"1111");        System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getGrand());        s.study();        s.eat();            }}

【员工案例】

  假如我们在开发一个系统时需要对员工类进行设计,员工包含3个属性:姓名、工号以及工资。经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。请使用继承的思想设计出员工类和经理类。要求类中提供必要的方法进行属性访问。

/*    分析:        普通员工类            成员变量:姓名、工号以及工资。            成员方法:工作        经理类:            成员变量:姓名、工号以及工资,奖金属性            成员方法:工作                实现:        员工类:        普通员工类:        经理类:*///定义员工类abstract class Employee {    //姓名、工号以及工资    private String name;    private String id;    private int salary;        public Employee() {}        public Employee(String name,String id,int salary) {        this.name = name;        this.id = id;        this.salary = salary;    }        public String getName() {        return name;    }        public void setName(String name) {        this.name = name;    }        public String getId() {        return id;    }        public void setId(String id) {        this.id = id;    }        public int getSalary() {        return salary;    }        public void setSalary(int salary) {        this.salary = salary;    }        //工作    public abstract void work();}//普通员工类class Programmer extends Employee {    public Programmer(){}        public Programmer(String name,String id,int salary) {        super(name,id,salary);    }        public void work() {        System.out.println("按照需求写代码");    }}//经理类class Manager extends Employee {    //奖金    private int money; //bonus 奖金    public Manager(){}        public Manager(String name,String id,int salary,int money) {        super(name,id,salary);        this.money = money;    }        public void work() {        System.out.println("跟客户谈需求");    }        public int getMoney() {        return money;    }        public void setMoney(int money) {        this.money = money;    }}class AbstractTest4 {    public static void main(String[] args) {        //测试普通员工        Employee emp = new Programmer();        emp.setName("林青霞");        emp.setId("czbk001");        emp.setSalary(18000);        System.out.println(emp.getName()+"---"+emp.getId()+"---"+emp.getSalary());        emp.work();        System.out.println("-------------");        emp = new Programmer("林青霞","czbk001",18000);        System.out.println(emp.getName()+"---"+emp.getId()+"---"+emp.getSalary());        emp.work();        System.out.println("-------------");                /*        emp = new Manager();        emp.setName("刘意");        emp.setId("czbk002");        emp.setSalary(8000);        emp.setMoney(2000);        */        //由于子类有特有的内容,所以我们用子类来测试        Manager m = new Manager();        m.setName("刘意");        m.setId("czbk002");        m.setSalary(8000);        m.setMoney(2000);        System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"---"+m.getMoney());        m.work();        System.out.println("-------------");                //通过构造方法赋值        m = new Manager("刘意","czbk002",8000,2000);        System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"---"+m.getMoney());        m.work();    }}

2.5 抽象类的补充问题

【补充问题一】

  一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?

  答:可以。意义是:不让创建对象

【补充问题二】

  abstract不能和哪些关键字共存?

  private:冲突

  final:冲突
  static :意义

abstract class Fu {    //public abstract void show();    //非法的修饰符组合: abstract和private    //private abstract void show();        //非法的修饰符组合    //final abstract void show();            //非法的修饰符组合    static abstract void show();        public static void method() {        System.out.println("method");    }}class Zi extends Fu {    public void show() {}}class AbstractDemo3 {    public static void main(String[] args) {        Fu.method();    }}

三、接口

3.1 接口概述

  继续回到我们的猫狗案例,我们想想狗一般就是看门,猫一般就是作为宠物了。但是,现在有很多的驯养员或者是驯兽师,可以训练出:猫钻火圈,狗跳高,狗做计算等。而这些额外的动作,并不是所有猫或者狗一开始就具备的,这应该属于经过特殊的培训训练出来的。所以,这些额外的动作定义到动物类中就不合适,也不适合直接定义到猫或者狗中,因为只有部分猫狗具备这些功能。所以,为了体现事物功能的扩展性,Java中就提供了接口来定义这些额外功能,并不给出具体实现,将来哪些猫狗需要被培训,只需要这部分猫狗把这些额外功能实现即可。

3.2 接口的特点

  1. 接口用关键字interface表示
    interface 接口名 {}
  2. 类实现接口用implements表示
    class 类名 implements 接口名 {}
  3. 接口不能实例化
    那么,接口如何实例化呢?按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态。
  4. 接口的子类
    可以是抽象类。但是意义不大。可以是具体类。要重写接口中的所有抽象方法。(推荐方案)

  由此可见,多态一共有3种类型:

  A:具体类多态(几乎没有)

  B:抽象类多态(常用)
  C:接口多态(最常用)

//定义动物培训接口interface AnimalTrain {    public abstract void jump();}//抽象类实现接口abstract class Dog implements AnimalTrain {}//具体类实现接口class Cat implements AnimalTrain {    public void jump() {        System.out.println("猫可以跳高了");    }}class InterfaceDemo {    public static void main(String[] args) {        //AnimalTrain是抽象的; 无法实例化        //AnimalTrain at = new AnimalTrain();        //at.jump();                AnimalTrain at = new Cat();        at.jump();    }}

3.3 接口成员特点

  • 成员变量:只能是常量,并且是静态的。默认修饰符:public static final
  • 构造方法:接口没有构造方法。因为接口主要是扩展功能的,而没有具体存在

  • 成员方法:只能是抽象方法。默认修饰符:public abstract
interface Inter {    public int num = 10;    public final int num2 = 20;    public static final int num3 = 30;        //错误: 需要
<标识符>
//public Inter() {} //接口方法不能带有主体 //public void show() {} //abstract void show(); //默认public public void show(); //默认abstract}//所有类都默认继承Object 类//接口名+Impl这种格式是接口的实现类格式class InterImpl implements Inter { public InterImpl() { super(); } public void show() {}}//测试类class InterfaceDemo2 { public static void main(String[] args) { //创建对象 Inter i = new InterImpl(); System.out.println(i.num); System.out.println(i.num2); //i.num = 100; //i.num2 = 200; //System.out.println(i.num); //无法为最终变量num分配值 //System.out.println(i.num2);//无法为最终变量num2分配值 System.out.println(Inter.num); System.out.println(Inter.num2); System.out.println("--------------"); }}

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

【类与类】

   继承关系,只能单继承,可以多层继承。

【类与接口】

  实现关系,可以单实现,也可以多实现。并且还可以在继承一个类的同时实现多个接口。

【接口与接口】

  继承关系,可以单继承,也可以多继承。

interface Father {    public abstract void show();}interface Mother {    public abstract void show2();}interface Sister extends Father,Mother {}//class Son implements Father,Mother //多实现class Son extends Object implements Father,Mother {    public void show() {        System.out.println("show son");    }        public void show2() {        System.out.println("show2 son");    }}class InterfaceDemo3 {    public static void main(String[] args) {        //创建对象        Father f = new Son();        f.show();        //f.show2(); //报错            Mother m = new Son();        //m.show(); //报错        m.show2();    }}

3.5 抽象类和接口的区别

【成员区别】

  抽象类:

    成员变量:可以变量,也可以常量
    构造方法:有
    成员方法:可以抽象,也可以非抽象
  接口:
    成员变量:只可以常量
    成员方法:只可以抽象

【关系区别】

  类与类

    继承,单继承
  类与接口
    实现,单实现,多实现
  接口与接口
    继承,单继承,多继承

【设计理念区别】

  抽象类:被继承体现的是”is a”的关系。抽象类中定义的是该继承体系的共性功能。

  接口:被实现体现的是”like a”的关系。接口中定义的是该继承体系的扩展功能。

3.6 接口的练习

【猫狗案例】——加入跳高的额外功能

/*    分析:从具体到抽象        猫:            姓名,年龄            吃饭,睡觉        狗:            姓名,年龄            吃饭,睡觉                    由于有共性功能,所以,我们抽取出一个父类:        动物:            姓名,年龄            吃饭();            睡觉(){}                    猫:继承自动物        狗:继承自动物                跳高的额外功能是一个新的扩展功能,所以我们要定义一个接口        接口:            跳高                    部分猫:实现跳高        部分狗:实现跳高    实现;        从抽象到具体            使用:        使用具体类*///定义跳高接口interface Jumpping {    //跳高功能    public abstract void 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 String getName() {        return name;    }        public void setName(String name) {        this.name = name;    }        public int getAge() {        return age;    }        public void setAge(int age) {        this.age = age;    }        //吃饭();    public abstract void eat();        //睡觉(){}    public void sleep() {        System.out.println("睡觉觉了");    }}//具体猫类class Cat extends Animal {    public Cat(){}        public Cat(String name,int age) {        super(name,age);    }        public void eat() {        System.out.println("猫吃鱼");    }}//具体狗类class Dog extends Animal {    public Dog(){}        public Dog(String name,int age) {        super(name,age);    }        public void eat() {        System.out.println("狗吃肉");    }}//有跳高功能的猫class JumpCat extends Cat implements Jumpping {    public JumpCat() {}        public JumpCat(String name,int age) {        super(name,age);    }    public void jump() {        System.out.println("跳高猫");    }}//有跳高功能的狗class JumpDog extends Dog implements Jumpping {    public JumpDog() {}        public JumpDog(String name,int age) {        super(name,age);    }    public void jump() {        System.out.println("跳高狗");    }}class InterfaceTest {    public static void main(String[] args) {        //定义跳高猫并测试        JumpCat jc = new JumpCat();        jc.setName("哆啦A梦");        jc.setAge(3);        System.out.println(jc.getName()+"---"+jc.getAge());        jc.eat();        jc.sleep();        jc.jump();        System.out.println("-----------------");                JumpCat jc2 = new JumpCat("加菲猫",2);        System.out.println(jc2.getName()+"---"+jc2.getAge());        jc2.eat();        jc2.sleep();        jc2.jump();    }}

【老师和学生案例】——加入抽烟的额外功能

/*    分析:从具体到抽象        老师:姓名,年龄,吃饭,睡觉        学生:姓名,年龄,吃饭,睡觉                由于有共性功能,我们提取出一个父类,人类。                人类:            姓名,年龄            吃饭();            睡觉(){}                    抽烟的额外功能不是人或者老师,或者学生一开始就应该具备的,所以,我们把它定义为接口                抽烟接口。        部分老师抽烟:实现抽烟接口        部分学生抽烟:实现抽烟接口            实现:从抽象到具体            使用:具体*///定义抽烟接口interface Smoking {    //抽烟的抽象方法    public abstract void smoke();}//定义抽象人类abstract class Person {    //姓名    private String name;    //年龄    private int age;        public Person() {}        public Person(String name,int age) {        this.name = name;        this.age = age;    }        public String getName() {        return name;    }        public void setName(String name) {        this.name = name;    }        public int getAge() {        return age;    }        public void setAge(int age) {        this.age = age;    }        //吃饭();    public abstract void eat();        //睡觉(){}    public void sleep() {        System.out.println("睡觉觉了");    }}//具体老师类class Teacher extends Person {    public Teacher() {}        public Teacher(String name,int age) {        super(name,age);    }        public void eat() {        System.out.println("吃大白菜");    }}//具体学生类class Student extends Person {    public Student() {}        public Student(String name,int age) {        super(name,age);    }        public void eat() {        System.out.println("吃红烧肉");    }}//抽烟的老师class SmokingTeacher extends Teacher implements Smoking {    public SmokingTeacher() {}        public SmokingTeacher(String name,int age) {        super(name,age);    }    public void smoke() {        System.out.println("抽烟的老师");    }}//抽烟的学生class SmokingStudent extends Student implements Smoking {    public SmokingStudent() {}        public SmokingStudent(String name,int age) {        super(name,age);    }    public void smoke() {        System.out.println("抽烟的学生");    }}class InterfaceTest2 {    public static void main(String[] args) {        //测试学生        SmokingStudent ss = new SmokingStudent();        ss.setName("林青霞");        ss.setAge(27);        System.out.println(ss.getName()+"---"+ss.getAge());        ss.eat();        ss.sleep();        ss.smoke();        System.out.println("-------------------");                SmokingStudent ss2 = new SmokingStudent("刘意",30);        System.out.println(ss2.getName()+"---"+ss2.getAge());        ss2.eat();        ss2.sleep();        ss2.smoke();    }}

【教练和运动员案例】

  乒乓球运动员和篮球运动员。乒乓球教练和篮球教练。  

  为了出国交流,跟乒乓球相关的人员都需要学习英语。

  请用所学知识:分析,这个案例中有哪些抽象类,哪些接口,哪些具体类。

//定义一个说英语的接口interface SpeakEnglish {    //说英语    public abstract void speak();}//定义人的抽象类abstract class Person {    private String name;    private int age;        public Person() {}        public Person(String name,int age) {        this.name = name;        this.age = age;    }        public String getName() {        return name;    }        public void setName(String name) {        this.name = name;    }        public int getAge() {        return age;    }        public void setAge(int age) {        this.age = age;    }        //睡觉    public void sleep() {        System.out.println("人都是要睡觉的");    }        //吃饭    public abstract void eat();}//定义运动员抽象类abstract class Player extends Person {    public Player() {}        public Player(String name,int age) {        super(name,age);    }        //学习    public abstract void study();}//定义教练抽象类abstract class Coach extends Person {    public Coach() {}        public Coach(String name,int age) {        super(name,age);    }        //教    public abstract void teach();}//定义乒乓球运动员具体类class PingPangPlayer extends Player implements SpeakEnglish {    public PingPangPlayer(){}        public PingPangPlayer(String name,int age) {        super(name,age);    }        //吃    public void eat() {        System.out.println("乒乓球运动员吃大白菜,喝小米粥");    }        //学习    public void study() {        System.out.println("乒乓球运动员学习如何发球和接球");    }        //说英语    public void speak() {        System.out.println("乒乓球运动员说英语");    }}//定义篮球运动员具体类class BasketballPlayer extends Player {    public BasketballPlayer(){}        public BasketballPlayer(String name,int age) {        super(name,age);    }        //吃    public void eat() {        System.out.println("篮球运动员吃牛肉,喝牛奶");    }        //学习    public void study() {        System.out.println("篮球运动员学习如何运球和投篮");    }}//定义乒乓球教练具体类class PingPangCoach extends Coach implements SpeakEnglish {    public PingPangCoach(){}        public PingPangCoach(String name,int age) {        super(name,age);    }        //吃    public void eat() {        System.out.println("乒乓球教练吃小白菜,喝大米粥");    }        //教    public void teach() {        System.out.println("乒乓球教练教如何发球和接球");    }        //说英语    public void speak() {        System.out.println("乒乓球教练说英语");    }}//定义篮球教练具体类class BasketballCoach extends Coach {    public BasketballCoach(){}        public BasketballCoach(String name,int age) {        super(name,age);    }        //吃    public void eat() {        System.out.println("篮球教练吃羊肉,喝羊奶");    }        //教    public void teach() {        System.out.println("篮球教练教如何运球和投篮");    }}class InterfaceDemo {    public static void main(String[] args) {        //测试运动员(乒乓球运动员和篮球运动员)        //乒乓球运动员        PingPangPlayer ppp = new PingPangPlayer();        ppp.setName("王浩");        ppp.setAge(33);        System.out.println(ppp.getName()+"---"+ppp.getAge());        ppp.eat();        ppp.sleep();        ppp.study();        ppp.speak();        System.out.println("----------------");        //通过带参构造给数据(留给你们)                //篮球运动员        BasketballPlayer bp = new BasketballPlayer();        bp.setName("姚明");        bp.setAge(34);        System.out.println(bp.getName()+"---"+bp.getAge());        bp.eat();        bp.sleep();        bp.study();        //bp.speak(); //没有该方法            }}

 

转载于:https://www.cnblogs.com/yft-javaNotes/p/10829845.html

你可能感兴趣的文章