学习笔记,仅供参考
面向对象
多态
多态向上转型和向下转型
我们首先通过以下代码复习一下自动类型提升和强制类型转换:
class BunnyAnimal0602 {
public static void main(String[] args) {
int i = 10;
byte b = 20;
i = b; //自动类型提升
b = (byte)i; //强制类型转换
}
}
由此,我们引出多态中的向上转型和向下转型:
class BunnyAnimal0602 {
public static void main(String[] args) {
Father f = new Son();
f.method();
}
}
class Father {
int num = 10;
public void print() {
System.out.println("Print Father");
}
}
class Son extends Father {
int num = 20;
public void print() {
System.out.println("Print Son");
}
public static void method() {
System.out.println("Method Son");
}
}
报错信息:
---------- javac ----------
BunnyAnimal0602.java:4: 错误: 找不到符号
f.method();
^
符号: 方法 method()
位置: 类型为Father的变量 f
1 个错误
Output completed (2 sec consumed) - Normal Termination
父类引用指向子类对象就是向上转型。同时,我们看到在上述代码中,由于父类中没有method方法,所以编译时报错。
下面我们通过向下转型,去调用子类中的method方法:
class BunnyAnimal0602 {
public static void main(String[] args) {
Father f = new Son();
System.out.println(f.num);
Son s = (Son)f;
s.method();
}
}
class Father {
int num = 10;
public void print() {
System.out.println("Print Father");
}
}
class Son extends Father {
int num = 20;
public void print() {
System.out.println("Print Son");
}
public static void method() {
System.out.println("Method Son");
}
}
输出:
10
Method Son
内存图:
多态的好处和弊端
- 多态的好处
- 提高代码的维护性
- 提高代码的扩展性
- 多态的弊端
- 不能使用子类特有的属性和行为
- 举个例子(多态的好处)
class AnimalBunnyCat {
public static void main(String[] args) {
method(new Bunny());
method(new Cat());
}
public static void method(Animal a) {
a.eat();
}
}
class Animal {
public void eat() {
System.out.println("动物吃饭");
}
}
class Bunny extends Animal {
public void eat() {
System.out.println("兔子吃胡萝卜");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
}
输出:
兔子吃胡萝卜
猫吃鱼
- 举个例子(强转)
基于上面的代码,我们给method增加一些功能,如果输入参数是Cat的对象,则增加Cat特有的功能,如果输入参数是Bunny的对象,则增加Bunny特有的功能:
class AnimalBunnyCat {
public static void main(String[] args) {
method(new Bunny());
method(new Cat());
}
public static void method(Animal a) {
if (a instanceof Bunny) {
Bunny b = (Bunny)a;
b.eat();
b.play();
} else if (a instanceof Cat) {
Cat c = (Cat)a;
c.eat();
c.sleep();
} else {
a.eat();
}
}
}
class Animal {
public void eat() {
System.out.println("动物吃饭");
}
}
class Bunny extends Animal {
public void eat() {
System.out.println("兔子吃胡萝卜");
}
public void play() {
System.out.println("兔子玩耳朵");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
public void sleep() {
System.out.println("猫睡觉");
}
}
输出:
兔子吃胡萝卜
兔子玩耳朵
猫吃鱼
猫睡觉
关键字instanceof
为判断前面的引用是否是后面的数据类型。如果没有经过instanceof
判断,我们可能会把Cat强制转换为Bunny这样就会出现类型转换异常ClassCastException