一、多态
1.1 多态概述
多态是指,同一个对象(事物),在不同时刻体现出来的不同状态。
举例::
猫可以是猫的类型。猫 m = new 猫();
同时猫也是动物的一种,也可以把猫称为动物。动物 d = new 猫();
再举一个例子:
水在不同时刻的状态:液体,固体,气态
1.2 多态的前提
- 要有继承关系。
- 要有方法重写。
其实没有也是可以的,但是如果没有这个就没有意义。 动物 d = new 猫(); d.show(); 动物 d = new 狗(); d.show();
- 要有父类引用指向子类对象。
父 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 多态的好处和弊端
【多态的好处】
- 提高了代码的维护性(继承保证)
- 提高了代码的扩展性(由多态保证)
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); //40 k爹.teach(); //讲解论语 //k爹.playGame(); //这是儿子才能做的
讲完了,下班回家了。脱下爹的装备,换上自己的装备
//向下转型 孔子 k = (孔子) k爹; System.out.println(k.age); //20 k.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 抽象类的特点
- 抽象类和抽象方法必须用abstract关键字修饰
格式 abstract class 类名 {} public abstract void eat();
- 抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类
- 抽象类不能实例化
因为它不是具体的。那么,抽象类如何实例化呢? 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。Animal a = new Cat(); 抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢? 用于子类访问父类数据的初始化
- 抽象的子类
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 接口的特点
- 接口用关键字interface表示
interface 接口名 {}
- 类实现接口用implements表示
class 类名 implements 接口名 {}
- 接口不能实例化
那么,接口如何实例化呢? 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态。
- 接口的子类
可以是抽象类。但是意义不大。 可以是具体类。要重写接口中的所有抽象方法。(推荐方案)
由此可见,多态一共有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(); //没有该方法 } }