多態 概念:指同一操作作用於某一類對象,可以有不同的解釋,產生不同的執行結果; 存在的必要條件 ① 需要存在繼承和實現關係; ② 同樣的方法調用而執行不同操作,運行不同代碼(重寫操作); ③ 在運行時父類或者介面的引用變數可以引用其子類的對象; 作用 ① 多態通過分離做什麼和怎麼做,從另一個角度將接
多態
概念:指同一操作作用於某一類對象,可以有不同的解釋,產生不同的執行結果;
存在的必要條件
① 需要存在繼承和實現關係;
② 同樣的方法調用而執行不同操作,運行不同代碼(重寫操作);
③ 在運行時父類或者介面的引用變數可以引用其子類的對象;
作用
① 多態通過分離做什麼和怎麼做,從另一個角度將介面和實現進行分離;
② “多態”則消除了類型之間耳朵耦合關係;
③ 多態的存在提高了程式的擴展和後期的可維護性;
1 public class AnimalDemo{
2 public static void main(String []args){
3 //父類的引用變數可以引用其子類對象
4 Animal animal1=new Dog("旺財");
5 animal1.eat();
6
7 Animal animal2=new Cat("招財");
8 animal2.eat();
9
10 }
11 }
12
13 class Animal{
14 private String name;
15 public Animal(String name){
16 this.name=name;
17 }
18
19 //這是一個通用的方法,實現沒有太大的意義
20 //只是告訴其子類去實現它
21 public void eat(){
22
23 }
24 }
25
26 class Dog extends Animal{
27 public Dog(String name){
28 super(name);
29 }
30
31 //對父類的方法進行重寫
32 public void eat(){
33 System.out.println("啃骨頭");
34 }
35 }
36
37 class Cat extends Animal{
38 public Cat(String name){
39 super(name);
40 }
41
42 //對父類的方法進行重寫
43 public void eat(){
44 System.out.println("吃魚");
45 }
46 }
View Code
對象上下轉型
① 由子類轉型成父類,在繼承圖上是向上移動的,一般稱為向上轉型;
② 向上轉型是從一個較專用類型像較通用類型轉型,所以總是安全的,也就是說,子類是父類的一個超集;
③ 向上轉型過程中,類介面中唯一可能發生的事情就是丟失方法,而不是獲取方法;
④ 與之相反的操作是向下轉型,不安全(可能需要instanceof操作符協助);
⑤ LSP(liskov替換原則):子類型必須能夠替換掉它們的基類型;
⑥ 安全的上轉和LSP的實施,充分體現繼承的“is-a”關係;
上面的demo就是向上轉型
1 public class AnimalDemo{
2 public static void main(String []args){
3 //父類的引用變數可以引用其子類對象
4 Animal animal1=new Dog("旺財狗");//向上轉型
5 //向上轉型首先是安全的,但可能會導致子類方法的丟失
6 //父類的引用變數只能調用父類中有的方法,或子類中重寫的方法
7 animal1.eat();
8 //animal1.sleep();//在dog中的特有方法不能使用
9
10 Animal animal2=new Cat("招財貓");
11 animal2.eat();
12
13
14 //向下轉型是不安全的
15 //Cat cat=(Cat)animal1;//轉換異常
16
17 }
18 }
19
20 class Animal{
21 private String name;
22 public Animal(String name){
23 this.name=name;
24 }
25
26 //這是一個通用的方法,實現沒有太大的意義
27 //只是告訴其子類去實現它
28 public void eat(){
29
30 }
31 }
32
33 class Dog extends Animal{
34 public Dog(String name){
35 super(name);
36 }
37
38 //對父類的方法進行重寫
39 public void eat(){
40 System.out.println("啃骨頭");
41 }
42
43 public void sleep(){
44 System.out.println("睡覺");
45 }
46 }
47
48 class Cat extends Animal{
49 public Cat(String name){
50 super(name);
51 }
52
53 //對父類的方法進行重寫
54 public void eat(){
55 System.out.println("吃魚");
56 }
57 }
View Code
instanceof運算符用來在運行時通過返回一個布爾值來指出對象是否是特定類或者是它的子類的一個實例;
用法:
result=object instanceof calss
result:布爾類型
object:必選項,任意對象表達式
class:必選項,任意已定義的對象類
說明:如果object是class或者其子類的一個實例,則instanceof運算符返回true,如果不是或者object是null,則返回false;
典型使用場合:在對對象做下轉型之前,沒有其它有關對象類型信息時務必使用instanceof來判斷一下,以免拋出ClassCastException異常;
1 public class AnimalDemo{
2 public static void main(String []args){
3 //父類的引用變數可以引用其子類對象
4 Animal animal1=new Dog("旺財狗");//向上轉型
5 //向上轉型首先是安全的,但可能會導致子類方法的丟失
6 //父類的引用變數只能調用父類中有的方法,或子類中重寫的方法
7 animal1.eat();
8 //animal1.sleep();//在dog中的特有方法不能使用
9
10 Animal animal2=new Cat("招財貓");
11 animal2.eat();
12
13
14 //向下轉型是不安全的
15 //Cat cat=(Cat)animal1;//轉換異常
16
17 //解決方法
18 if(animal1 instanceof Cat){
19 //未進入
20 System.out.println("進入執行");
21 Cat cat=(Cat)animal1;
22 }
23
24 if(animal2 instanceof Cat){
25 //進入
26 System.out.println("進入執行2");
27 Cat cat=(Cat)animal2;
28 cat.sleep();
29 }
30
31 }
32 }
33
34 class Animal{
35 private String name;
36 public Animal(String name){
37 this.name=name;
38 }
39
40 //這是一個通用的方法,實現沒有太大的意義
41 //只是告訴其子類去實現它
42 public void eat(){
43
44 }
45 }
46
47 class Dog extends Animal{
48 public Dog(String name){
49 super(name);
50 }
51
52 //對父類的方法進行重寫
53 public void eat(){
54 System.out.println("啃骨頭");
55 }
56
57 public void sleep(){
58 System.out.println("睡覺");
59 }
60 }
61
62 class Cat extends Animal{
63 public Cat(String name){
64 super(name);
65 }
66
67 //對父類的方法進行重寫
68 public void eat(){
69 System.out.println("吃魚");
70 }
71
72 public void sleep(){
73 System.out.println("睡覺");
74 }
75 }
View Code
動態綁定和靜態綁定
概念:
① 在程式執行前方法以及被綁定,針對Java簡單的可以理解為程式編譯期的綁定(靜態綁定)java當中的方法是final,static,private和構造方法都是前期綁定的;
② 運行時,根據變數實際引用的對象類型決定調用哪個方法(動態綁定);
靜態綁定在編譯期進行
Person.sayHi();
動態綁定在運行期進行
Person p=new Teacher();
p.sayHi();
多態的概念基於對象引用的動態綁定特性;
多態應用
簡單來說,多態是具有表現多種行為能力的特征;
同一個實現介面,使用不同的實例而執行不同操作;
不使用多態:
1 public class PrinterDemo{
2 public static void main(String []args){
3 ColorPrinter cp=new ColorPrinter("惠普");
4 BlackPrinter bp=new BlackPrinter("戴爾");
5 School school=new School();
6 //school.setColorPrinter(cp);
7 school.setBlackPrinter(bp);//新建的黑白列印時,要修改學習的列印方法
8 school.print("hello java");
9
10 /*以上每次調用不同的子類時特別麻煩,會影響到其他類中的代碼修改*/
11 }
12 }
13
14 class Printer{
15 private String brand;
16
17 public Printer(String brand){
18 this.brand=brand;
19 }
20
21 public String getBrand()
22 {
23 return brand;
24 }
25
26 //列印方法應該由其子類來具體的實現
27 public void print(String content){
28
29 }
30 }
31
32
33 //開原原則:對修改是封閉的,對擴展是開放的
34 //可以使用多態解決這個問題,父類的引用變數可以引用其子類的對象
35 class School{
36 private ColorPrinter cp=null;
37 private BlackPrinter bp=null;
38 private ZhenPrinter bp=null;
39
40 //安裝彩色印表機
41 public void setColorPrinter(ColorPrinter cp){
42 this.cp=cp;
43 }
44
45 //安裝黑白印表機
46 public void setBlackPrinter(BlackPrinter bp){
47 this.bp=bp;
48 }
49
50 //安裝針式印表機
51 public void setZhenPrinter(ZhenPrinter bp){
52 this.bp=bp;
53 }
54
55 public void print(String content){
56 //交給中心所安裝的彩色印表機來列印
57 //cp.print(content);
58 //交給中心所安裝的黑白印表機來列印
59 bp.print(content);
60 }
61
62 }
63
64 class ColorPrinter extends Printer{
65 public ColorPrinter(String brand){
66 super(brand);
67 }
68 //對父類的方法進行重寫
69 public void print(String content){
70 System.out.println(getBrand()+"彩色列印:"+content);
71 }
72 }
73
74 class BlackPrinter extends Printer{
75 public BlackPrinter(String brand){
76 super(brand);
77 }
78 //對父類的方法進行重寫
79 public void print(String content){
80 System.out.println(getBrand()+"黑白列印:"+content);
81 }
82 }
83
84 class ZhenPrinter extends Printer{
85 public ZhenPrinter(String brand){
86 super(brand);
87 }
88 //對父類的方法進行重寫
89 public void print(String content){
90 System.out.println(getBrand()+"針式列印:"+content);
91 }
92 }
View Code
使用多態:
1 public class PrinterDemo{
2 public static void main(String []args){
3 ColorPrinter cp=new ColorPrinter("惠普");
4 BlackPrinter bp=new BlackPrinter("戴爾");
5 ZhenPrinter zp=new ZhenPrinter("戴爾");
6 School school=new School();
7
8 school.setPrinter(zp);//這裡的參數可以調用較靈活,使用cp,bp,zp都可以,而不用改school類中的方法
9 school.print("hello java");
10
11 }
12 }
13
14 class Printer{
15 private String brand;
16
17 public Printer(String brand){
18 this.brand=brand;
19 }
20
21 public String getBrand()
22 {
23 return brand;
24 }
25
26 //列印方法應該由其子類來具體的實現
27 public void print(String content){
28
29 }
30 }
31
32
33 //開原原則:對修改是封閉的,對擴展是開放的
34 //可以使用多態解決這個問題,父類的引用變數可以引用其子類的對象
35 class School{
36 private Printer p=null;//安裝印表機
37
38 //拿父類的引用變數作為參數,好處就是可以接受任何其子類的對象
39 //越是抽象的東西就是越穩定的
40 public void setPrinter(Printer p){
41 this.p=p;
42 }
43
44 public void print(String content){
45 //交給中心所安裝的印表機來列印
46 p.print(content);
47 }
48 }
49
50 class ColorPrinter extends Printer{
51 public ColorPrinter(String brand){
52 super(brand);
53 }
54 //對父類的方法進行重寫
55 public void print(String content){
56 System.out.println(getBrand()+"彩色列印:"+content);
57 }
58 }
59
60 class BlackPrinter extends Printer{
61 public BlackPrinter(String brand){
62 super(brand);
63 }
64 //對父類的方法進行重寫
65 public void print(String content){
66 System.out.println(getBrand()+"黑白列印:"+content);
67 }
68 }
69
70 class ZhenPrinter extends Printer{
71 public ZhenPrinter(String brand){
72 super(brand);
73 }
74 //對父類的方法進行重寫
75 public void print(String content){
76 System.out.println(getBrand()+"針式列印:"+content);
77 }
78 }
View Code