Java面向物件四大特性
1.多型 :晚繫結,執行時,一個介面,多種實現
- 面向物件的四大特性:封裝、繼承、多型、抽象。從一定角度來看,封裝和繼承幾乎都是為多型而準備的。是最重要的知識點。
- 多型的定義:指允許不同類的物件對同一訊息做出響應。即同一訊息可以根據傳送物件的不同而採用多種不同的行為方式。(傳送訊息就是函式呼叫)
- 實現多型的技術稱為:動態繫結(dynamic binding),是指在執行期間判斷所引用物件的實際型別,根據其實際的型別呼叫其相應的方法。
- 多型的作用:消除型別之間的耦合關係。
- 現實中,關於多型的例子不勝列舉。比方說按下 F1 鍵這個動作,如果當前在 Flash 介面下彈出的就是 AS 3 的幫助文件;如果當前在 Word 下彈出的就是 Word 幫助;在 Windows 下彈出的就是 Windows 幫助和支援。同一個事件發生在不同的物件上會產生不同的結果。(from http://www.cnblogs.com/jack204/archive/2012/10/29/2745150.html)
下面是多型存在的三個必要條件,要求大家做夢時都能背出來!
多型存在的三個必要條件
一、要有繼承;
二、要有重寫;
三、父類引用指向子類物件。
多型的好處:
1.可替換性(substitutability)。多型對已存在程式碼具有可替換性。例如,多型對圓Circle類工作,對其他任何圓形幾何體,如圓環,也同樣工作。
2.可擴充性(extensibility)。多型對程式碼具有可擴充性。增加新的子類不影響已存在類的多型性、繼承性,以及其他特性的執行和操作。實際上新加子類更容易獲得多型功能。例如,在實現了圓錐、半圓錐以及半球體的多型基礎上,很容易增添球體類的多型性。
3.介面性(interface-ability)。
4.靈活性(flexibility)。它在應用中體現了靈活多樣的操作,提高了使用效率。
5.簡化性(simplicity)。多型簡化對應用軟體的程式碼編寫和修改過程,尤其在處理大量物件的運算和操作時,這個特點尤為突出和重要。
Java中多型的實現方式:介面實現,繼承父類進行方法重寫,同一個類中進行方法過載。
例項:
- public class Wine {
- public void fun1(){
- System.out.println("Wine 的Fun.....");
- fun2();
- }
- public void fun2(){
- System.out.println("Wine 的Fun2...");
- }
- }
- public class JNC extends Wine{
- /**
- * @desc 子類過載父類方法
- * 父類中不存在該方法,向上轉型後,父類是不能引用該方法的
- * @param a
- * @return void
- */
- public void fun1(String a){
- System.out.println("JNC 的 Fun1...");
- fun2();
- }
- /**
- * 子類重寫父類方法
- * 指向子類的父類引用呼叫fun2時,必定是呼叫該方法
- */
- public void fun2(){
- System.out.println("JNC 的Fun2...");
- }
- }
- public class Test {
- public static void main(String[] args) {
- Wine a = new JNC();
- a.fun1();
- }
- }
- -------------------------------------------------
- Output:
- Wine 的Fun.....
- JNC 的Fun2...
例2: 多型==晚繫結。
不要把函式過載理解為多型。
因為多型是一種執行期的行為,不是編譯期的行為。
多型:父型別的引用可以指向子型別的物件。
比如 Parent p = new Child();
當使用多型方式呼叫方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤;
如果有,再去呼叫子類的該同名方法。
(注意此處,靜態static方法屬於特殊情況,靜態方法只能繼承,不能重寫Override,如果子類中定義了同名同形式的靜態方法,它對父類方法只起到隱藏的作用。呼叫的時候用誰的引用,則呼叫誰的版本。)
(參考學習連結:http://docs.oracle.com/javase/tutorial/java/IandI/override.html)
如果想要呼叫子類中有而父類中沒有的方法,需要進行強制型別轉換,如上面的例子中,將p轉換為子類Child型別的引用。
因為當用父類的引用指向子類的物件,用父類引用呼叫方法時,找不到父類中不存在的方法。這時候需要進行向下的型別轉換,將父類引用轉換為子類引用。
結合例項說明
主要講講兩種型別轉換和兩種編譯時候的錯誤。
[java] view plain copy
- public class PolyTest
- {
- public static void main(String[] args)
- {
- //向上型別轉換
- Cat cat = new Cat();
- Animal animal = cat;
- animal.sing();
- //向下型別轉換
- Animal a = new Cat();
- Cat c = (Cat)a;
- c.sing();
- c.eat();
- //編譯錯誤
- //用父類引用呼叫父類不存在的方法
- //Animal a1 = new Cat();
- //a1.eat();
- //編譯錯誤
- //向下型別轉換時只能轉向指向的物件型別
- //Animal a2 = new Cat();
- //Cat c2 = (Dog)a2;
- }
- }
- class Animal
- {
- public void sing()
- {
- System.out.println("Animal is singing!");
- }
- }
- class Dog extends Animal
- {
- public void sing()
- {
- System.out.println("Dog is singing!");
- }
- }
- class Cat extends Animal
- {
- public void sing()
- {
- System.out.println("Cat is singing!");
- }
- public void eat()
- {
- System.out.println("Cat is eating!");
- }
- }
例子的執行結果:
這段程式碼:
Cat類中定義了eat()方法,但是Animal類中沒有這個方法,a1引用是Animal類的,所以找不到,編譯時出錯:
兩種型別的型別轉換
(1)向上型別轉換(Upcast):將子型別轉換為父型別。
對於向上的型別轉換,不需要顯示指定,即不需要加上前面的小括號和父類型別名。
(2)向下型別轉換(Downcast):將父型別轉換為子型別。
對於向下的型別轉換,必須要顯式指定,即必須要使用強制型別轉換。
並且父型別的引用必須指向子類的物件,即指向誰才能轉換成誰。
不然也會編譯出錯:
因為父類引用指向的是Cat類的物件,而要強制轉換成Dog類,這是不可能的
2.抽象
對於面向物件程式設計來說,抽象是它的一大特徵之一。在Java中,可以通過兩種形式來體現OOP的抽象:介面和抽象類。這兩者有太多相似的地方,又有太多不同的地方。很多人在初學的時候會以為它們可以隨意互換使用,但是實際則不然。今天我們就一起來學習一下Java中的介面和抽象類。下面是本文的目錄大綱:
一.抽象類
二.介面
三.抽象類和介面的區別
若有不正之處,請多多諒解並歡迎批評指正,不甚感激。
請尊重作者勞動成果,轉載請標明原文連結:
http://www.cnblogs.com/dolphin0520/p/3811437.html
一.抽象類
在瞭解抽象類之前,先來了解一下抽象方法。抽象方法是一種特殊的方法:它只有宣告,而沒有具體的實現