title: 多态
date: 2021-10-29 14:19:03
tags: java笔记
#多态笔记
面向对象多态 先来看一个问题 首先,使用现有技术解决。仅展示部分代码
package com.hspedu.poly_.poly2;
public class Master {
//主人名称
private String name;
public Master(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//完成主任给小狗 喂食 骨头
public void feed(Dog dog, Food food) {
System.out.println("主人" + name + "给 " + dog.getName() + "喂食" + food.getName());
}
}
package com.hspedu.poly_.poly2;
public class Poly2 {
public static void main(String[] args) {
Master tom = new Master("tom");
Dog dog = new Dog("大黄");
Bone bone = new Bone("大骨棒");
tom.feed(dog,bone);
//现在我还需要一个xxx喂猫吃鱼的方法 该如何实现呢
//难道我需要再写一完成给小猫喂食的方法吗?
}
}
像下面这样
public void feed(Cat cat,Fish fish){ //构成方法重载
System.out.println("主人" + name + "给 " + cat.getName() + "喂食" + fish.getName());
}
// 方法调用
Master bob = new Master("bob");
Cat cat = new Cat("汤姆");
Fish fish = new Fish("鱼");
bob.feed(cat,fish);
这样的确可以实现此需求,可当我们假设有几百个动物需要喂,难道写几百个吗?
此时问题就暴露出来了:代码的复用性不高,而且不利于代码维护
解决方案: 引出多态机制:方法或者对象有多种形态。是面向对象的三大特征,多态是建立在封装和继承基础之上的。
-
方法的多态:重写和重载体现多态
public class PloyMethod { public static void main(String[] args) { //方法重载体现多态 //我们通过不同的参数去调用sum方法,就会去调用不同的方法,因此sum就是多态的体现 A a = new A(); System.out.println(a.sum(10,20)); System.out.println(a.sum(10,20,30)); // 方法重写体现多态 方法名相同,但是只调用自己类的say()方法 B b = new B(); a.say(); b.say(); } } -
对象的多态 (核心,困难,重点)
-
一个对象的编译类型和运行类型可以不一致
-
编译类型在定义对象时,就确定了,不能够改变
-
运行类型是可以变化的
//animal 编译类型 Animal 运行类型:Dog Animal animal = new Dog(); animal.cry(); animal = new Cat(); animal.cry(); -
编译类型看等号左边,运行类型看等号右边
-
public void feed(Animal animal, Food food) {
System.out.println("主人" + name + "在学校里给" + animal.getName() + "喂食" + food.getName());
}
多态注意事项和细节讨论
多态的前提是:两个对象类存在继承关系
多态的向上转型:
Animal animal = new Dog(); animal.cry() //找运行类型cry()
本质:父类的引用指向了子类的对象
语法:父类类型 引用名 = new 子类类型();
特点:
- 编译类看左边 Animal,运行类型看右边 Dog()
- 可以调用父类中的所有成员(需要遵守访问权限)
- 不能调用子类中的特有成员(即子类中特有的方法)
- 因为编译类型是animal 所以他根本不知道子类方法是谁 所以无法调用
public class T {
public static void main(String[] args) {
AA aa = new BB();
aa.test();
aa.pp() // ! 这里会报错 无法调用
}
}
class AA{
public void test(){
System.out.println("ok");
}
}
class BB extends AA{
public void pp(){
System.out.println("你好");
}
}
- 最终运行效果看子类的具体实现
多态的向下转型:
-
语法: 子类类型 引用名 = (子类类型)父类引用
-
public class T { public static void main(String[] args) { AA aa = new BB(); //子类类型 引用名 = (子类类型)父类引用 //bb 原来指向的就是aa对象 才可以向下转型 BB bb = (BB) aa; bb.pp(); } } class AA{ public void test(){ System.out.println("ok"); } } class BB extends AA{ public void pp(){ System.out.println("你好"); } }z -
只能强转父类的引用,不能强转父类的对象
-
要求父类的引用必须指向的是当前目标类型的对象
-
当向下转型后可以调用子类类型中的所有成员
属性不存在重写之说
package com.hspedu;
public class PolyDetail02 {
public static void main(String[] args) {
//属性没有重写之说,属性的值看编译类型
base base = new Sub(); //向上转型
System.out.println(base.count); //直接看编译类型 10
}
}
class base{
int count = 10;
}
class Sub extends base{
int count = 20;
}
instanceOf比较操作符,用于判断运行类型是否为XX或者XX的子类型



