多態(tài)
同一個對象,在不同時刻表現(xiàn)出來的不同形態(tài)
- 舉例
我們可以說貓是貓:貓 cat = new 貓();
我們也可以說貓是動物:動物 animal = new 貓();
這里貓在不同的時刻表現(xiàn)出來了不同的形態(tài),這就是多態(tài) - 多態(tài)的前提和體現(xiàn)
- 有繼承/實現(xiàn)關(guān)系
- 有方法重寫
- 有父類引用指向子類對象
public class Animal {
public void eat() {
System.out.println("動物吃東西");
}
}
public class Cat extends Animal { // 繼承
@Override // 重寫方法
public void eat() {
System.out.println("貓吃東西");
}
}
public static void main(String[] args) {
// 父類引用指向子類對象
Animal a = new Cat();
}
多態(tài)中成員訪問特點
- 成員變量: 編譯看左邊,執(zhí)行看左邊
- 成員方法: 編譯看左邊,執(zhí)行看右邊
為什么成員變量和成員方法的訪問不一樣呢? - 因為成員方法有重寫,而成員變量沒有
public class Animal {
public int age = 40;
public void eat() {
System.out.println("動物吃東西");
}
}
public class Cat extends Animal {
public int age = 30;
public int weight = 10;
@Override
public void eat() {
System.out.println("貓吃東西");
}
public void playGame() {
System.out.println("貓玩游戲");
}
}
public static void main(String[] args) {
// 由父類引用指向子類對象
Animal a = new Cat();
System.out.println(a.age);
// System.out.println(a.weight); // 編譯需要看左邊的Animal,看父類中有無
a.eat(); // 貓吃魚 運行看右邊,看子類中有無
// a.playGame(); // 編譯需要看左邊的Animal,看父類中有無
}
多態(tài)的好處和弊端
多態(tài)的好處: 提高了程序的擴(kuò)展性(具體體現(xiàn): 定義方法的時候,使用父類型作為參數(shù),將來在使用的時候,使用具體的子類型參與操作)
多態(tài)的弊端: 不能使用子類的特有功能
public class Animal {
public void eat() {
System.out.println("動物吃東西");
}
}
public class AnimalOperator {
/*public void useAnimal(Cat c) { // Cat c = new Cat();
c.eat();
}
public void useAnimal(Dog d) { // Dog d = new Dog();
d.eat();
}*/
public void useAnimal(Animal a) {
// Animal a = new Cat(); 編譯看左邊,執(zhí)行看右邊
a.eat();
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("貓吃魚");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃屎");
}
}
public static void main(String[] args) {
// 創(chuàng)建動物操作類的對象,調(diào)用方法
AnimalOperator ao = new AnimalOperator();
Cat c = new Cat();
ao.useAnimal(c); // 貓吃魚
Dog d = new Dog();
ao.useAnimal(d); // 狗吃屎
}
多態(tài)中的轉(zhuǎn)型
- 向上轉(zhuǎn)型: 從子到父,父類引用指向子類對象
- 向下轉(zhuǎn)型: 從父到子,父類引用轉(zhuǎn)為子類對象
public class Animal {
public void eat() {
System.out.println("動物吃東西");
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("貓吃魚");
}
public void playGame() {
System.out.println("貓玩游戲");
}
}
public static void main(String[] args) {
// 多態(tài)
Animal a = new Cat(); // 向上轉(zhuǎn)型
a.eat();
// a.playGame(); // 編譯看左邊,因為父類中沒有playGame(),所以不能通過編譯
// 那就是想用呢?
/*// 方法1: 創(chuàng)建Cat類的對象
Cat c = new Cat();
c.eat();
c.playGame(); // 但是,貓對象,當(dāng)然可以用貓的方法*/
// 方法2: 向下轉(zhuǎn)型
Cat c = (Cat)a; // 類似強制類型轉(zhuǎn)換
c.eat();
c.playGame();
}
多態(tài)轉(zhuǎn)型內(nèi)存圖解
多態(tài)轉(zhuǎn)型內(nèi)存圖解.png
多態(tài)轉(zhuǎn)型內(nèi)存圖解2.png
多態(tài)轉(zhuǎn)型內(nèi)存圖解3.png
多態(tài)轉(zhuǎn)型內(nèi)存圖解4.png
多態(tài)轉(zhuǎn)型內(nèi)存圖解5.png
多態(tài)轉(zhuǎn)型內(nèi)存圖解6.png
多態(tài)轉(zhuǎn)型內(nèi)存圖解7.png
多態(tài)轉(zhuǎn)型內(nèi)存圖解8.png
案例: 貓和狗
public 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 void eat() {
System.out.println("動物吃東西");
}
}
public class Cat extends Animal {
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("貓吃魚");
}
}
public class Dog extends Animal {
public Dog() {
}
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("狗吃屎");
}
}
public static void main(String[] args) {
Animal a = new Cat();
a.setName("黑貓");
a.setAge(5);
System.out.println(a.getName() + "," + a.getAge() + "歲");
a.eat();
Animal a2 = new Cat("白貓",6);
System.out.println(a2.getName() + "," + a2.getAge() + "歲" );
a2.eat();
}