類的多態性?
什麼體現了類的多態性?
多態是通過:
1 接口 和 實現接口並覆蓋接口中同一方法的幾不同的類體現的
2 父類 和 繼承父類並覆蓋父類中同一方法的幾個不同子類實現的.
一、基本概念
多態性:發送消息給某個對象,讓該對象自行決定響應何種行為。
通過將子類對象引用賦值給超類對象引用變量來實現動態方法調用。
java 的這種機制遵循一個原則:當超類對象引用變量引用子類對象時,被引用對象的類型而不是引用變量的類型決定了調用誰的成員方法,但是這個被調用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。
1. 如果a是類A的一個引用,那麼,a可以指向類A的一個實例,或者說指向類A的一個子類。
2. 如果a是接口A的一個引用,那麼,a必須指向實現了接口A的一個類的實例。
二、Java多態性實現機制
SUN目前的JVM實現機制,類實例的引用就是指向一個句柄(handle)的指針,這個句柄是一對指針:
一個指針指向一張表格,實際上這個表格也有兩個指針(一個指針指向一個包含了對象的方法表,另外一個指向類對象,表明該對象所屬的類型);
另一個指針指向一塊從java堆中為分配出來內存空間。
三、總結
1、通過將子類對象引用賦值給超類對象引用變量來實現動態方法調用。
DerivedC c2=new DerivedC();
BaseClass a1= c2; //BaseClass 基類,DerivedC是繼承自BaseClass的子類
a1.play(); //play()在BaseClass,DerivedC中均有定義,即子類覆寫了該方法
分析:
* 為什麼子類的類型的對象實例可以覆給超類引用?
自動實現向上轉型。通過該語句,編譯器自動將子類實例向上移動,成為通用類型BaseClass;
* a.play()將執行子類還是父類定義的方法?
子類的。在運行時期,將根據a這個對象引用實際的類型來獲取對應的方法。所以才有多態性。一個基類的對象引用,被賦予不同的子類對象引用,執行該方法時,將表現出不同的行為。
在a1=c2的時候,仍然是存在兩個句柄,a1和c2,但是a1和c2擁有同一塊數據內存塊和不同的函數表。
2、不能把父類對象引用賦給子類對象引用變量
BaseClass a2=new BaseClass();
DerivedC c1=a2;//出錯
在java裡面,向上轉型是自動進行的,但是向下轉型卻不是,需要我們自己定義強制進行。
c1=(DerivedC)a2; 進行強制轉化,也就是向下轉型.
3、記住一個很簡單又很複雜的規則,一個類型引用只能引用引用類型自身含有的方法和變量。
你可能說這個規則不對的,因為父類引用指向子類對象鄲時候,最後執行的是子類的方法的。
其實這並不矛盾,那是因為採用了後期綁定,動態運行的時候又根據型別去調用了子類的方法。而假若子類的這個方法在父類中並沒有定義,則會出錯。
例如,DerivedC類在繼承BaseClass中定義的函數外,還增加了幾個函數(例如 myFun())
分析:
當你使用父類引用指向子類的時候,其實jvm已經使用了編譯器產生的類型信息調整轉換了。
這裡你可以這樣理解,相當於把不是父類中含有的函數從虛擬函數表中設置為不可見的。注意有可能虛擬函數表中有些函數地址由於在子類中已經被改寫了,所以對象虛擬函數表中虛擬函數項目地址已經被設置為子類中完成的......
什麼是多態性?Java中的多態包含哪些類型?
多態性:顧名思義就是擁有“多種形態”的含義,是指屬性或方法在子類中表現為多種形態。它包括兩種類型:
靜態多態性:包括變量的隱藏、方法的重載(指同一個類中,方法名相同[方便記憶],但是方法的參數類型、個數、次序不同,本質上是多個不同的方法);
動態多態性:是指子類在繼承父類(或實現接口)時重寫了父類(或接口)的方法,程序中用父類(或接口)引用去指向子類的具體實例,從代碼形式上看是父類(或接口)引用去調用父類(接口)的方法,但是在實際運行時,JVM能夠根據父類(或接口)引用所指的具體子類,去調用對應子類的方法,從而表現為不同子類對象有多種不同的形態。不過,程序代碼在編譯時還不能確定調用的哪一個類的方法,只有在運行時才能確定,故又稱為運行時的多態性。
什麼是多態性,C++中是如何實現多態的
多態按字面的意思就是“多種狀態”。在面嚮對象語言中,接口的多種不同的實現方式即為多態。
多態性是允許你將父對象設置成為和一個或更多的他的子對象相等的技術,賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作。
把不同的子類對象都當作父類來看,可以屏蔽不同子類對象之間的差異,寫出通用的代碼,做出通用的編程,以適應需求的不斷變化。
賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作。也就是說,父親的行為像兒子,而不是兒子的行為像父親。
舉個例子:例如ATM機。世界上有非常多的銀行,每個銀行都有好多種卡。如果ATM需要為每一種卡寫一種方法去調用,例如getMoney(CCBCard card),getMoney(BBCard card)就會非常的麻煩。而且維護起來就是災難性的。因為每時每刻都可能會有新的卡出現。所以我們可以採用多態
getMoney(Card card),所有的銀行卡都繼承Card這個類。這樣就可以避免為每一種卡寫一個方法。但是每一種卡的使用方法,作用都不一樣,Card如何調用每一種卡不同的內容呢?
這就需要多態。讓你看起來像是操作的父類,但是實際的運行內容卻是子類的內容。
下面有一段代碼,你可以參考一下。
用父類的指針或者引用指向子類對象,來實現多態的作用
class A {
public:
A() {}
virtual void foo() {
cout << "This is A." << endl;
}
};
class B : public A {
public:
B() {}
void foo() {
cout << "This is B." << endl;
}
};
int main(int argc, char* argv[]) {
A *a = new B();
a->foo();
if(a != NULL)
delete a;
return 0;
}
這將顯示:
This is B.
如果把virtual去掉,將顯示:
This is A.
前面的多態實現使用抽象類,並定義了虛方法.
什麼是多態?
比如有一個父類superClass,它有2個子類subClass1,subClass2。superClass有一個方法
func(),兩個子類都重寫了這個方法。那麼我們可以定義一個superClass的引用obj,讓它指向一個子類的對象,比如superClass obj = new subClass1();那麼我們調用obj.func()方法時候,會進行動態綁定,也就是obj它的實際類型的func()方法,即subClass1的func()方法。同樣你寫superClass obj = new subClass2();obj.func()其實調用的是subCla憨s2的func()方法。這種由於子類重寫父類方法,然後用父類引用指向子類對象,調用方法時候會進行動態綁定,這就是多態。多態對程序的擴展具有非常大的作用,比如你要再有一個subClass3,你需要改動的東西會少很多,要是使用了配置文件那就可以不動源代碼了。
C++中類的繼承,多態性的要點是什麼
多態性
1.多態性的概念
多態性是指用一個名字定義不同的函數,這函數執行不同但又類似的操作,從而實現“一個接口,多種方法”。
多態性的實現與靜態聯編、動態聯編有關。靜態聯編支持的多態性稱為編譯時的多態性,也稱靜態多態性,它是通過函數重載和運算符重載實現的。動態聯編支持的多態性稱為運行時的多態性,也稱動態多態性,它是通過繼承和虛函數實現的。
2.函數重載
函數重載的意義在於他能用同一個名字訪問一組相關的函數。
在類中普通成員函數和構造函數都可以重載,特別是構造函數的重載(他提供了多種初使化方式)給用戶更大的靈活性。在基類和派生類的函數重載有兩種情況:一種是參數有所差別的重載。另一種是參數沒有差別的重載,只是他們屬於不同的類。
可以用以下兩種方法來區分這兩種函數:用對象名加以區分;使用“類名::”加以區分。
3.運算符重載稱動態多態性,他是通過繼承和虛函數實現的。
運算符重載通過創建運算符函數operator@()來實現。運算符函數定義了重載的運算符將要進行的操作,這種操作通常作用在一個類上。這樣,在編譯時遇到名為operator@的運算符函數(@表示所要重載的運算符),就檢查傳遞給函數的參數的類型。
重載運算符與預定義運算符的使用方法完全相同,它不能改變原有運算符的參數個數(單目或雙目),也不能改變原有的優先級的結合性。用戶不能定義新的運算符,只能從C++已有的運算符中選擇一個恰當的運算符重載。
3.1成員運算符函數
運算符函數可以定義為它將要操作的類的成員(稱為成員運算符函數),也可以定義為非類的成員,但是非成員的運算符函數大多是類的友元函數(稱為友元運算符函數)。
成員運算符函數在類中的聲明格式為:
class X{
//……
type operator@(參數表);
};
其中type為函數的返回類型,@為所要重載的運算符符號,X是重載此運算符的類名,參數表中羅列的是該運算符所需要的操作數。
成員運算符函數定義的形式一般為:
type X::operator@(參數表)
//函數體}
其符號的含義與聲明時相同。
在成員運算符函數的參數表中,若運算符是單目的,則參數表為空,此時當前對象作為運算符的一個操作數,通過this指針隱含地傳遞給函數的;若運算符是雙目的,則參數表中有一個操作數,它作為運算符的右操作參數,此時當前對象做為運算符的左操作數,它是this指針隱含地傳遞給函數的。總之成員運算符函數operator@所需要的一個操作數是由對象通過this指針隱含傳遞。
3.2友元運算符函數
在C++中可以把運算符函數定義成某個類的友元函數,稱為友元運算符函數。
友元運算符函數在類的內部聲明格式如下:
friend type operator@(參數表)
定義友元運算符函數格式如下:
type operator@(參數表)
{ //函數體
}
與成員運算符函數不同,友元運算符函數是不屬於任何類對象的,它沒有this指針。若重載的是雙目運算符,則參數表中有兩個操作數;若重載的是單目運算符,則參數表中只有一個操作數。 不能用友元函數重載的運算符是=、()、[]、-〉,其餘的運算符都可以使用友元函數來實現重載。
運算符函數調用形式如下表:
運算符函數調用形式
習慣形式 友元運算符函數調用形式 成員運算符函數調用形式
a+b operator(a,b) a.ope......
C#類的多態性指的是什麼?
沒法實例化,那個是內部類,得定義為publ丁c才行,而且這個跟多態沒關係。
改成:
public class m就可以了
實例化代碼如下:
pt.m pm = new pt.m();
java中多態是什麼意思?
多態性是指允許不同類的對象對同一消息作出響應。多態性包括參數化多態性和包含多態性。多態性語言具有靈活、抽象、行為共享、代碼共享的優勢,很好的解決了應用程序函數同名問題。
多態有兩種表現形式:重載和覆蓋
首先說重載(overload),是發生在同一類中。與什麼父類子類、繼承毫無關係。
標識一個函數除了函數名外,還有函數的參數(個數和類型)。也就是說,一個類中可以有兩個或更多的函數,叫同一個名字而他們的參數不同。
他們之間毫無關係,是不同的函數,只是可能他們的功能類似,所以才命名一樣,增加可讀性,僅此而已!
再說覆蓋(override),是發生在子類中!也就是說必須有繼承的情況下才有覆蓋發生。
我們知道繼承一個類,也就有了父類了全部方法,如果你感到哪個方法不爽,功能要變,那就把那個函數在子類中重新實現一遍。
這樣再調用這個方法的時候,就是執行子類中的過程了。父類中的函數就被覆蓋了。(當然,覆蓋的時候函數名和參數要和父類中完全一樣,不然你的方法對父類中的方法就不起任何作用,因為兩者是兩個函數,毫不關係)
java的多態怎麼理解啊,多態有什麼用途。
多態有編譯時多態 和運行時多態。
第一個是通過方法重載實現;第二個是通過方法覆蓋實現(子類覆蓋父類方法)。
第一種就是我們調用方法是不用區分參數類型,程序會自動執行相應方法,如: 加法運算,可以使int相加,可以是double相加,都是同一個方法名。
第二種就是動態綁定,使用父類引用指向子類對象,再調用某一父類中的方法時,不同子類會表現出不同結果。 這樣的作用就是擴展性極好,玩過網遊的話應該知道 遊戲中有不同的角色,它們都有一個父類,它們做相同動作時表現出來的效果就會不一樣,比如跑,魔法師的跑跟戰士的跑就不會一樣,這就是倆者都覆蓋了父類中的跑方法,各自有自己的現實,表現出來多態。 如果有一天你想再加個角色,只用再寫一個類繼承該父類,覆蓋其中的跑方法就行了,其他代碼不用怎麼改,所以可維護性也很好。
這一個小的程序 或許你體會不到多態的強度作用。其實說到多態就是 面向接口編程,它不和具體類盡心掛鉤了
比如 你沒用多態的話 ,
你沒實例化一個對象 就要new一下,那假如你那天改變了需求了呢?那是不是又要改裡面的?這樣不好,所以 你可以通過多態,把需要相似的給提出來,然後繼承它 這樣 以後需要擴展你僅僅只是繼承而已。這樣就很簡單。
這個需要多看代碼 才可以更深刻理解。
有問題在討論。
對象的多態性到底有什麼用?
通俗點,比如:筆類有三個子類:毛筆、鋼筆、鉛筆,他們有方法:使用前準備()這個方法, 毛筆的方法執行:蘸墨 鋼筆執行:吸墨 鉛筆執行:削鉛筆
這樣你可以在寫字這個類裡寫:筆 對象 = 對象.使用前準備()。
這樣你的這個類就抽象出來了。將來你再多了一個沾水鋼筆就可以在沾水鋼筆裡修改屬性為:蘸墨水 而不用進入寫字類再加上一個筆的子類判斷。
明白不?
你問這個問題說明你沒有理解面向對象。還要繼續努力。
____________________________________________________
看見了你的補充,說的不完全對,但是好想你明白一些了。
其實不是為了以後的變更,而是為了更通用。
例如:寫字(寫信)等等這個對象不應該與筆這個對象之間建立強耦合,否則將來發明瞭新的筆,你就都要去修改寫字這個類,但是如何具體些是筆的寫這個方法應該說明的,所以將兩個類抽象出來,這樣,你的類可以給任意的其他人去使用,以後因為變更而擴展是用途之一。
C++中 繼承與多態區別
繼承是指,子類可以自動獲得父類提供的函數,如父類提供了foo函數,則子類也會有foo函數
多態是指,子類可以重寫父類的某個函數,從而為這個函數提供不同於父類的行為。一個父類的多個子類可以為同一個函數提供不同的實現,從而在父類這個公共的接口下,表現出多種行為
當然,以上的自動獲得和重寫,還存在一個訪問級別的概念。比如public的函數或者protected的函數才能被重寫這類的限制。