09.01 多态的概念
- A:概念
- 同一个对象在不同时刻体现出来的不同状态
- B:前提
- a: 要有继承
- b: 要有方法重写
- c: 要有父类引用指向子类对象
C:分类
a: 具体类多态
class Fu {} class Zi extends Fu {} Fu f = new Zi();
b: 抽象类多态
abstract class Fu {} class Zi extends Fu {} Fu f = new Zi();
c: 接口多态
interface Fu {} class Zi implements Fu {} Fu f = new Zi();
09.02 多态中的成员访问特点
- A:成员变量
- 编译看左边(父类),运行看左边(父类)
- 内存图
- B:构造方法
- 子类的构造都会默认访问父类构造
- C:成员方法
- 编译看左边(父类),运行看右边(子类)(动态绑定)
- 内存图
D:静态方法
- 编译看左边(父类),运行看左边(父类)
静态方法与类相关,算不上重写,所以还是在左边
class Demo_Polymorphic { public static void main(String[] args) { Father f = new Son(); System.out.println(f.num);//10 f.print();//Son print f.method();//Father static method Son s = new Son(); System.out.println(s.num);//20 } } class Father { int num = 10; public void print() { System.out.println("Father print"); } public static void method() { System.out.println("Father static method"); } } class Son extends Father { int num = 20; public void print() { System.out.println("Son print"); } public static void method() { System.out.println("Father static method"); } }
09.03 超人的故事
A: 案例分析
class Test_SuperMan { public static void main(String[] args) { Person p = new SuperMan();//父类引用指向子类对象,超人提升为人,向上转型 System.out.println(p.name); p.business(); SuperMan sm = (SuperMan)p;//向下转型 //p.fly(); sm.fly(); } } class Person { String name = "Join"; public void business() { System.out.println("谈生意"); } } class SuperMan extends Person{ String name = "SuperMan"; public void business() { System.out.println("谈几个亿的生意"); } public void fly() { System.out.println("我要救人"); } }
现象:子可以当作父使用,父不能当作子使用。
09.04 多态的向上转型和向下转型
- A:向上转型
从子到父 - B:向下转型
从父到子 - C: 内存图
09.04 多态的好处和弊端
- 多态的好处:
- A:提高代码的维护性(继承体现)
- B:提高代码的扩展性(多态体现)
- 多态的弊端:
- 父不能使用子的特有功能。
现象:
子可以当作父使用,父不能当作子使用。
*案例演示class Demo_Animal { public static void main(String[] args) { method(new Cat());//Animal a = new Cat(); 开发中很少在创建对象的时候用父类引用去指向子类对象,直接创建子类对象 method(new Dog()); } public static void method(Animal a) { //关键字:instanceof判断前边的引用是否是后边的数据类型 if(a instanceof Cat) { Cat c = (Cat)a; c.eat(); c.catchMouse(); }else if(a instanceof Dog) { Dog d = (Dog)a; d.eat(); d.lookhome(); }else { a.eat(); } } } class Animal { public void eat() { System.out.println("Animal eat "); } } class Dog extends Animal{ public void eat() { System.out.println("Dog eat "); } public void lookhome() { System.out.println("Dog lookhome "); } } class Cat extends Animal{ public void eat() { System.out.println("Cat eat "); } public void catchMouse() { System.out.println("Cat catchMouse "); } }
09.05 面试题分析
/*
看程序写结果:先判断有没有问题,如果没有,写出结果
多态的成员访问特点:
方法:编译看左边,运行看右边。
继承的时候:
子类中有和父类中一样的方法,叫重写。
子类中没有父亲中出现过的方法,方法就被继承过来了。
*/
class DuoTaiTest {
public static void main(String[] args) {
A a = new B();
a.show();//爱 类A的show里的show2调用类B的show2
B b = new C();
b.show();//你 类B的show方法继承自A类,show方法里调用的show2为C类的show2
}
}
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("你");
}
}
09.06 抽象类的概述及其特点
A: 概念
把多个共性的东西提取到一个类中,这是继承的做法。但是呢,这多个共性的东西,在有些时候,方法声明一样,但是方法体。
也就是说,方法声明一样,但是每个具体的对象在具体实现的时候内容不一样。
所以,我们在定义这些共性的方法的时候,就不能给出具体的方法体。
而一个没有具体的方法体的方法是抽象的方法。
在一个类中如果有抽象方法,该类必须定义为抽象类。- B: 抽象类的特点
- A:抽象类和抽象方法必须用关键字abstract修饰
- abstract class 类名{}
- public abstract void 方法名();
- B:抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类
- C:抽象类不能实例化
- 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
- D:抽象类的子类
- a:是一个抽象类。
- b:是一个具体类。这个类必须重写抽象类中的所有抽象方法。
- A:抽象类和抽象方法必须用关键字abstract修饰
09.07 抽象类的成员特点
A:成员变量
有变量,有常量
B:构造方法
有构造方法
C:成员方法
有抽象,有非抽象
09.08 抽象类的练习
A:猫狗案例练习
/* 猫狗案例 具体事物:猫,狗 共性:姓名,年龄,吃饭 分析:从具体到抽象 猫: 成员变量:姓名,年龄 构造方法:无参,带参 成员方法:吃饭(猫吃鱼) 狗: 成员变量:姓名,年龄 构造方法:无参,带参 成员方法:吃饭(狗吃肉) 因为有共性的内容,所以就提取了一个父类。动物。 但是又由于吃饭的内容不一样,所以吃饭的方法是抽象的, 而方法是抽象的类,类就必须定义为抽象类。 抽象动物类: 成员变量:姓名,年龄 构造方法:无参,带参 成员方法:吃饭(); 实现:从抽象到具体 动物类: 成员变量:姓名,年龄 构造方法:无参,带参 成员方法:吃饭(); 狗类: 继承自动物类 重写吃饭(); 猫类: 继承自动物类 重写吃饭(); */ //定义抽象的动物类 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(); //练习:测试猫类 } } B:老师案例练习 C:学生案例练习 D:员工案例练习
09.09 抽象类的面试题(掌握)
A:抽象类有构造方法,不能实例化,那么构造方法有什么用?
用于子类访问父类数据的初始化
B:一个类如果没有抽象方法,却定义为了抽象类,有什么用?
可以,为了不让创建对象,交给子类完成
C:abstract不能和哪些关键字共存
a:final 冲突 被final修饰的不让子类重写,所以重复
b:private 冲突 private修饰的类是不让子类访问的
c:static 无意义 被staic修饰的类可以通过类名调用,但是调用抽象方法是没有意义的
09.10 接口的概述及其特点
- A: 接口概述
- 从广义上讲对外提供规则的都是接口
- 从狭义上讲指java中的interface
- B: 接口的特点
- a: 接口的关键字interface表示
- interface 接口名{}
- b: 接口的是先用implements 表示
- class 类名 implements 接口名{}
- c: 接口不能实例化
- d:接口的实现类
- a:是一个抽象类。意义不大
- b:是一个具体类,这个类必须重写接口中的所有抽象方法。(推荐方案)
- a: 接口的关键字interface表示
09.11 接口的成员特点
- A: 接口的成员特点:
- A:成员变量
只能是常量
默认修饰符:public static final - B:构造方法
没有构造方法 - C:成员方法
只能是抽象的
默认修饰符:public abstract
- A:成员变量
09.12 类与类,类与接口,接口与接口
- A:类与类 extends
- 继承关系,只能单继承,可以多层继承
B:类与接口
class 类名 implements A,B
- 实现关系,可以单实现,也可以多实现。
- 还可以在继承一个类的同时,实现多个接口
C:接口与接口
interface InterA extends InterB,InterC {…}
- 继承关系,可以单继承,也可以多继承
09.13抽象类和接口的区别(必记)?
A: 成员区别
- 抽象类:
- 成员变量:可以常量,可以变量
- 成员方法:可以抽象,可以非抽象
- 构造方法:有
- 接口:
- 成员变量:只能常量 public static final
- 成员方法:只可以抽象
- 构造方法:无
- 抽象类:
B: 关系区别:
- 类与类:
- 继承,单继承
- 类与接口:
- 实现,单实现,多继承
- 接口与接口:
- 继承,单继承,多继承
- 类与类:
- C: 设计理念不同
- 抽象类:is a,抽象类中定义的是共性功能。
- 接口:like a,接口中定义的是扩展功能。
09.14 练习:
A:猫狗案例,加入跳高功能
/* 猫狗案例,加入跳高的额外功能 分析:从具体到抽象 猫: 姓名,年龄 吃饭,睡觉 狗: 姓名,年龄 吃饭,睡觉 由于有共性功能,所以,我们抽取出一个父类: 动物: 姓名,年龄 吃饭(); 睡觉(){} 猫:继承自动物 狗:继承自动物 跳高的额外功能是一个新的扩展功能,所以我们要定义一个接口 接口: 跳高 部分猫:实现跳高 部分狗:实现跳高 实现; 从抽象到具体 使用: 使用具体类
*/
//定义跳高接口
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(); //定义跳高狗并进行测试的事情自己完成。 }
}
- B:老师和学生案例,加入抽烟功能0