Board logo

主題: [轉貼] 什麼是多型的解釋 [打印本頁]

發表人: jocosn    時間: 2005-4-17 09:25 AM     主題: [轉貼] 什麼是多型的解釋

同名異式(Polymorphism)=多型=動態繫結(Dynamic binding)

1. 定義相同名稱的操作,以不同的方式處理不同類型的資料
2. 多型在程式執行期利用動態連結(Dynamic Binding)的方式判斷訊息參數的類型
 與個數來決定運作的方法。
3. 達到物件導向中「多型」的方法
  抽象類別 (abstract class):
  抽象類別是為了讓方法的使用更多樣化,物件轉換型別為抽象類別後,即使
  方法名稱相同,其實作的內容與執行結果卻不同。


by 朱孝國

[jocosn 在 2005-4-17 09:26 AM 作了最後編輯]
發表人: Acute    時間: 2005-4-17 07:58 PM


引用:
jocosn寫到:
同名異式(Polymorphism)=多型=動態繫結(Dynamic binding)

2. 多型在程式執行期利用動態連結(Dynamic Binding)的方式判斷訊息參數的類型
 與個數來決定運作的方法。
by 朱孝國


不知道是說哪個語言
但是以C++ 而言, 這一段不太對勁
C++ 的多形性靠的是編譯時期就決定好該呼叫哪個函式
C++ 的作法其實很簡單, 例如你寫個function 叫做Power ()
實際上, 他翻出來的函式名稱是Power!@#$%^ (), 後面那一串髒話, 就是參數的型態資訊
所以, 多形很容易就可以在編譯時期決定好, 該呼叫誰, 因為名字被偷改了

就正常的角度來看, 如果執行時期才去辨認參數... 決定呼叫哪個函式...
那程式的額外負擔有多重阿...
如果真有程式語言使用執行時期判斷多形性... 那寫出來的程式... 在4G 的CPU 上執行, 可能比隨便用個其他語言寫同樣效果的程式, 在100M 的CPU 執行還要慢
況且... 程式如何在執行時期才去辨認參數的型態跟個數, 恐怕都是一個無解的問題哩

Acute.
發表人: GERRYccc    時間: 2005-4-18 11:33 AM

我猜喔~~純屬猜測..........
你想問的是不是 屬於 函數重載 的部份?!...
聽起來好像是這部份的樣子,可以 同一個函數名稱+不同的資料型態,在依使用者輸入的型態之後再決定執行哪個函數
詳情請參見書上提到函數重載的部份^^"
發表人: swimman    時間: 2005-4-19 02:23 AM

樓主的這種說法是沒錯不過比較抽象
比較實際的例子像是SHAPE形狀是一個父類別,有一個抽象的方法是計算面積
而有三角形和圓形兩種子類別
利用shape來宣告但是實例可能是三角形或是圓形是在執行期才能確定
也就編譯期無法確定必須在執行期才能確定,也就是必須LATE Binding
那麼在RUNTIME時計算面積就會有不同的行為
或是宣告一個介面跟繼承介面實做的CLASS也是一樣
發表人: jocosn    時間: 2005-4-19 05:39 AM

依留言順序回答


引用:
Acute寫到:

引用:
jocosn寫到:2. 多型在程式執行期利用動態連結(Dynamic Binding)的方式判斷訊息參數的類型與個數來決定運作的方法。

不知道是說哪個語言
但是以C++ 而言, 這一段不太對勁
C++ 的多形性靠的是編譯時期就決定好該呼叫哪個函式
......
所以, 多形很容易就可以在編譯時期決定好, 該呼叫誰, 因為名字被偷改了
....

抱歉,沒講清楚是用那種語言。
我轉貼的多型解釋講的應該是 Java,一時不查,sorry。



引用:
Acute寫到:
就正常的角度來看, 如果執行時期才去辨認參數... 決定呼叫哪個函式...
那程式的額外負擔有多重阿...
...........

這我不知道負擔有多重,因為我的 C++  是在 10 年前學的,那時 OO 觀念才剛在台灣萌芽,standard C++ 還沒出來,各家編譯器實作也不同。至於現在,我幾乎沒寫過 C++ 程式,所以不知道他執行的速度。不過,Java 跑起來很慢倒是真的。它的 GUI 也做的很醜很爛。

...(之前錯誤範例,刪掉,以免造成事後看的人誤解)....

在這篇 http://www.microsoft.com/taiwan/ ... nctionPointer_1.htm 有提到Java 和 C++ 都是用 Virtual Table,我不知道真假,我沒看過 Java 實現多型的內部機制文章。C++ 倒是有看過。
我沒記錯的話,C++  對於要達到多型的手法都要宣告methods為 virtual;但是 Java 不用,預設動作就是。


不過因為小神童的提醒,我再仔細看了一下這段,如果是針對 Java,會比較有問題
3. 達到物件導向中「多型」的方法
  抽象類別 (abstract class):
  抽象類別是為了讓方法的使用更多樣化,物件轉換型別為抽象類別後,即使
  方法名稱相同,其實作的內容與執行結果卻不同。

不一定是指抽象類別,Java 有所謂的 interface(C++是以 pure abstract class 來表示 interface 的概念),甚至是一般類別也可以做到。所以我覺得這篇多型文章前後矛盾。
事後加註:多型的手法不只是靠抽象類別,還要靠繼承。

剛找到一篇 C++ 的,有興趣的人可以參考一下。
http://squall.cs.ntou.edu.tw/cpp ... iding_Overload.html

-------------------------------------------------------------------

引用:
GERRYccc寫到:
我猜喔~~純屬猜測..........
你想問的是不是 屬於 函數重載 的部份?!..............

是指多載overload ? 還是覆載override?
電腦名詞的中文名稱很混亂。
有人認為 overloade 和 override 都是多型,有人認為 override 才是。

[jocosn 在 2005-4-20 01:29 PM 作了最後編輯]
發表人: Acute    時間: 2005-4-19 08:58 AM

呼... 文章內分段引言真的很累, 我就不引了, 直接說比較快

其實我特別寫了個例子, 就是怕中文翻譯上造成困擾, 有沒有發現, 我沒有說1, 3 兩點錯, 我只說針對第二點說明是錯的 ^^"
在class 內的function 因為繼承而產生的override, 其實是因為物件已經不同

我特別舉例, Power() function 具備不同參數時, 單提到function 行為, 而不提class 行為, 來顯示compiler 會怎麼去處理一個非class function 情形下, 多形如何真實達到.

其實class 也是利用類似觀念, 我們這樣想好了, 如果程式真的是所謂的, 執行時期去辨認物件, 那我們來思考一件最基本的動作, 一個compiler or 一個interpreter 如何去產生一段runtime 程式碼, 用來辨認物件? 那其實是幾乎永遠做不到的, 讓你自己寫一段程式碼, 然後可以任由user 定義一個物件, 然後你可以去辨識他, 你想一想, 你要寫的多複雜, 才能達到變認不出錯呢? 呵

在compiler 的實作方法上, 不同的class 具有不同的member, 即使繼承之後, 兩個相同名字的function, 其實已經分別隸屬於不同的兩個object, 因此, 他跟使用object 不同名字的function 意思是一樣的, 程式執行時期並沒有辨認上的困擾或需求, 他本來就已經決定好該怎麼去call, 因為物件已經不同. 只是從source level 去看時, 明明一樣的東西(名稱相同), 而他能準確的去call 不同的東西, 如此而已.

再用另一個簡單的角度去看, 如果, 如果, 如果, 程式是執行時期才去辨認該用哪個function, 那麼程式很輕易的就會掉入一個陷阱裏面, 假設function Power 有三種型態, 分別是: Power (int, int), Power (char, char), Power (int, char)
今天寫程式的人沒留意到, 寫了一個Power (char, int), 那麼, 這個錯誤是不是要等到執行時期才發現他錯? compiler 沒有能力也不該有能力發現他錯誤呢? 因為compiler 並不負責去辨認該怎麼call, right ? 可是實際上, 不管使用哪一種OO 語言, 他都是在compiler 時期就被挑出來的錯誤, 呵

當然, 某些特別的語言, 可能可以在compiler 之前就利用interpreter 先執行看看, 這時候, 就很難用我們習慣的說法去說, 他算不算執行時期才去辨認, 但是, 所謂執行時期才去辨認, 應該定義為: 程式有能力在執行時期辨認object, 而這個辨認行為不是藉由"監督程式, 或稱之為虛擬機器去達成的", 因為interpreter 可以"看見"整個程式的架構跟繼承關係, 他有能力辨認, 就跟compiler 有能力辨認一樣, 因為他是外部的解釋器, 他已經針對不同的東西, 建立一個lookup table, 所以, 他可以靠這份table 來索引相對關係上的物件, 而不是內部的"執行時期程式碼", 兩者其實不能等同論之.

再舉另一個限制來說明他是靠compiler 做到的. 在C++ 裏面, 我們可以用cast 的方法, 去改變基本型態, 例如, 你可以把int 透過cast 變成char or double, 但是, 他不允許你去cast 一個object or class, 為何不行呢? 如果compiler 編譯出來的程式具備"辨認物件"的能力, 那他幹嘛限制不允許cast 一個class? 只是辨認一下就搞定了不是嗎? 呵

不管哪一種語言, 他可以定義出不會混淆的語法機制及想要實現的語言願景即可, 但是, compiler 終究是一個程式, compiler要能被實作, so, 當真正實作時, 很多事情就會需要把他"確定"下來, 否則compiler就寫不出來了.

我不是很確定, 語言的定義者, 是不是真的用類似1F 那種說法 --- "多型在程式執行期利用動態連結(Dynamic Binding)的方式判斷訊息參數的類型與個數來決定運作的方法", 這種規定一定要怎麼做才可以的, 我個人認為, "語言定義者" 很少這麼幹, 因為把"實作"該怎麼做定義死, 會導致這個語言無法被開發出來才對, 因為只要實作上達不到語言要求, 就是一種錯誤, 況且, 這種說法, 意味著我前面說的, 如果call 一個function, 但是使用的參數沒有可以對應到的function, 這種現象, 應該等到執行時期才可以發現. 這種"強制解釋", 通常都是其他書籍作者"橫加"解釋上去的.以下舉個C 的例子來說這件事情.

C 語言裏面, 從來未曾規定, 參數傳遞上, 在堆疊內該怎麼做, 但是, 很多C 語言的書, 只要提到參數傳遞順序, 一定"斬釘截鐵"的說, C 語言的參數由後往前推入堆疊. 為什麼呢? 這部份是一個"實作"結果論, 因為, C 語言有個動態參數機制, 參數數目可以不是固定的, K&R 這項定義, 導致所有寫C compiler 的人, 只能由後往前將參數推入堆疊, 才能實作compiler, 不然compiler 做不出來. 當然, K&R 也從未說, 實際的參數, 由runtime辨認參數數目決定之, 因為這樣子, 大概又打死一堆寫compiler 的人. 當然, C 這種古老語言, 他定義的東西都比較單純而容易了解, 而且, 也不擔心把負擔加諸程式設計者身上, 從某個角度來看, 動態參數的確是可以解釋為: "執行時期辨認", 只不過, 這段辨認的code, 需要寫程式的人自己去負責, compiler 只是很簡單的提供幾個有關參數處理的function 給寫程式的人使用, 如此而已, 呵

沒頭沒尾敲了一大堆, 我想解釋的只是, 動態連結是無法在諸多條件不明的情形下完成的(也就是, 需要去辨認東西), jocosn提到Virtual Table, 其實這也是"實作" C++ 時產生的一種機制, Virtual Table並非完全runtime 才產生, compiler 已經先決定好這個table, 而載入時期, 已經把這個table 建立起來, 執行時期, 已經被決定怎樣使用這個table, 而不是執行時期才根據辨認結果來決定怎樣使用這個table, MS 也充分利用這個table 概念, 完成OLE 以及後來所有OLE 衍生出來的新規格 (個人對MS 的規格很少留意, so, OLE 之後啥米COM, DCOM... 一路的名詞沒去記 ^^").

呵, 這篇文該結尾了. 一些新的語言, 碰觸越來越少, 也很懶得再去看語言的定義, 都是遇到時, 看看sample 然後就隨手亂寫一通, 不寫Windows 程式有個快樂的地方, 就是不用看太多複雜而抽象的規格資料, 也不用被規定的死死的寫程式, CPU 任由自己高興的控制, 真是快樂阿, 哈

^^" 希望上述沒有寫錯的地方, 萬一有寫錯之處, 也歡迎繼續討論.

Acute.
發表人: jocosn    時間: 2005-4-19 10:11 AM

小神童你好神阿,短短時間就可以打出這麼多東西。
你真是有料的人阿,怪不得稱為小神童。可惜我看 2 段就眼花了。
我先送你一隻花,不過東西太長,我先抓一個重點問問。
我很好奇其他 3 朵花是誰送的?



引用:

我們來思考一件最基本的動作, 一個compiler or 一個interpreter 如何去產生一段runtime 程式碼


配合下列這一段

引用:

如果, 程式是執行時期才去辨認該用哪個function, 那麼程式很輕易的就會掉入一個陷阱裏面, 假設function Power 有三種型態, 分別是: Power (int, int), Power (char, char), Power (int, char)
今天寫程式的人沒留N到, 寫了一個 Power (char, int), 那麼, 這個錯誤是不是要等到執行時期才發現他錯? compiler 沒有能力也不該有能力發現他錯誤呢? 因為compiler 並不負責去辨認該怎麼call, right ? 可是實際上, 不管使用哪一種OO 語言, 他都是在compiler 時期就被挑出來的錯誤, 呵


加上原文
多型在程式執行期利用動態連結(Dynamic Binding)的方式.....

這裡所說的「動態連結(Dynamic Binding)」,不知道 Acute 是怎麼定義或去看?
我對底層沒有研究,有錯請加以指正。
舉一個例子,compile 時會先編譯多個 functions,執行時配合 object 型態去呼叫那一個 function,這就叫做動態連結,所以只要在記憶體還是哪裡配置一個區塊,專放物件要存放的資料就好。
所以沒有產生額外的程式碼,只有產生額外的資料。

至於 Power (char, int) 這個錯誤如果等到執行時期才發現,我覺得應該會因為沒有定義到這個 function,所以當然編譯錯誤,不用等到執行,這好像跟多型沒關係?就像你呼叫一個你沒定義的變數 X 一樣。

哈,我覺得我好像不太對!
因為抓不到小神童要問的重點!

[jocosn 在 2005-4-19 10:31 AM 作了最後編輯]
發表人: Acute    時間: 2005-4-19 11:37 AM


引用:
jocosn寫到:
加上原文
多型在程式執行期利用動態連結(Dynamic Binding)的方式.....

這裡所說的「動態連結(Dynamic Binding)」,不知道 Acute 是怎麼定義或去看?
我對底層沒有研究,有錯請加以指正。
舉一個例子,compile 時會先編譯多個 functions,執行時配合 object 型態去呼叫那一個 function,這就叫做動態連結,所以只要在記憶體還是哪裡配置一個區塊,專放物件要存放的資料就好。
所以沒有產生額外的程式碼,只有產生額外的資料。

至於 Power (char, int) 這個錯誤如果等到執行時期才發現,我覺得應該會因為沒有定義到這個 function,所以當然編譯錯誤,不用等到執行,這好像跟多型沒關係?就像你呼叫一個你沒定義的變數 X 一樣。


我的意思就是, 原文的描述是一種錯誤阿 @_@
我們來看動態連結應該是啥
首先, DLL 稱之為, 動態連結程式庫. 他為何叫做動態連結程式庫? 因為compiler/linker 不知道應該跟誰連結, 只知道, 程式被指定, 要去呼叫一個外部的東西, 這個東西, 至少要等到執行時期的載入階段, 才能確認.  這種動態連結, 其實也是已經知道一切, 只是最終的程式碼在載入時期才去找到, 並且連結, so, 他並不是執行時期才根據啥去判斷, 他做不到, 他是載入時期. 根據指定的程式庫去找到程式碼, 並且完成連結, 之後執行.

動態連結程式庫允許執行時期進行連結, 但是, 不好意思, compiler/linker 沒能力做, 必須程式撰寫者, 自己去進行載入, 並且進行連結, 以C/C++ 來看, 就是載入後, 利用函式指標去指到正確的function. 為什麼要程式設計師自己做? 因為動態連結沒辦法去辨認, 那太困難了, 寫程式的人知道自己在幹嘛, so, 讓寫程式的人自己動手, 簡單又乾脆. 如果要compiler/linker 幫忙, 一律只能在載入時期就必須決定!

再來看OO 語言的多形性的例子, 先來看純function 的部份, 他沒有任何辨識或判斷, 也沒有需要等到執行時期才知道, 在compiler 時期, 就已經決定好一切, 該call 哪個function, so, 他沒有任何所謂執行時期的動態連結行為發生. 而C++ compiler 也用一個最簡單的作法, 把參數條件加入實際function name裏面, 所以, linker 變得很簡單. 把這個稱之為"執行時期利用動態連結..." 我覺得是不對的. 因為他本來就是預先決定好的, 而不是臨時才決定, compiler 早就賦予每個不同參數的function 有不同的"名字", 只是撰寫程式者, 看到的是同一個"名字" 而已.

再來看複雜一點的class or object 行為, class A 有個function A, class A2 繼承class A, 然後一樣有個function A, 從人去看, 沒錯, 都是叫做A, 可是, 從compiler 去看, 他知道class A 跟A2 是不同的東西, 在compiler 時期, 他就已經可以知道, 當你要呼叫function A 時, 是呼叫class A or class A1 的function A. so, 他跟純function 意思還是一樣的, 在compiler 時期, 所有一切都已經決定好, 他還是不能稱之為執行時期利用動態連結...

如果OO 語言真的具備動態連結能力, 應該是要能正確執行以下程式: (這是無法compiler 的程式)

void Power (int i, j);
void Power (char a, char b);
void Power (int, char);

functionDiffcult (void *p1, void *p2, void *p3, void *p4)
{
      Power (*p1, *p2);
      Power (*p3, *p4);
      Power (*p3, *p1);
}

functionEasy ()
{
     char a, b;
     int i, j;
     void *p1, *p2;

     p1 = &a;
     p2 = &b;
     Power (*p1, *p2);

     p1 = &i;
     Power (*p1, *p2);

     p2 = &j;
     Power (*p1, *p2);

     FunctionDiffcult (&a, &b, &i, &j);
     FunctionDiffcult (&i, &j, &a, &b);
}

上面的程式, 只是一個示意碼, 或者稱之為虛擬碼, 他不能compiler 也不能執行, 我要解釋的只是, 哪個語言有能力去根據一個不知道型態的內容, 然後執行時期去辨認他是啥型態, 然後決定該怎樣call !

事實上, OO 語言都是compiler 已經根據資料型態, 預先決定好該實際去call 哪個function, 而不是"執行時期根據參數型態動態連結", 如果是, 那應該要有一個語言有能力compiler & 執行上面那一段虛擬碼. 程式能夠去"辨認" 參數是啥, 然後決定呼叫三個function 當中的哪一個. 但是, 這是不可能可以做到的

Acute.
發表人: jocosn    時間: 2005-4-19 02:28 PM

那應該怎麼改才對?
發表人: swimman    時間: 2005-4-19 10:58 PM


引用:
jocosn寫到:
依留言順序回答



我舉一個 Java 的例子

CODE:
[Copy to clipboard]
class A {
     void myInstanceMethod( ) {
         System.out.println("Class A's instance method.");
     }
}

class B extends A {        // extends 表示繼承
   void myInstanceMethod(int a) {
        System.out.println("Class B's instance method.");
   }
}

class Demo {
    public static void main (String args[ ]) {
        A obj = new B();
        obj.myInstanceMethod(5);     // Class B's instance method ??? ---problem X
    }
}
[jocosn 在 2005-4-19 06:17 AM 作了最後編輯]


既然obj是用A宣告的  當然就以為他是A,不論obj是怎麼NEW的
所以就只有一個不帶參數的myInstanceMethod方法
用B的myInstanceMethod(int)方法compiler在邊譯期就會檔下來,根本就進不了RUNTIME
除非強制轉型
強制轉型後就轉為RUNTIME的時期才進行檢查

基本上函數的OVERLOADING並不是什麼了不起的東西
根據C++的函式語意學
C++會將函數名稱跟所使用參數加在一起成為新的函數名稱
所以函數名稱一樣參數不一樣就會變成不同的函數
所以在邊譯期就可以進行檢查知道要叫哪一個函數
這也就意味著回傳值的不同是不能構成可以辨別的新涵數
基本上OVERLOADING跟多型是沒有關係的
發表人: Acute    時間: 2005-4-20 01:23 AM


引用:
jocosn寫到:
那應該怎麼改才對?


2. 多型在程式編譯時期利用判斷訊息參數的類型與個數來決定運作的方法。

應該這樣子, 比較合理 ^^"

Acute.
發表人: jocosn    時間: 2005-4-20 01:36 AM

感謝 swimman 的解釋,小弟有幾點疑問,還請幫忙釐清:



引用:
swimman寫到:
所以就只有一個不帶參數的 myInstanceMethod 方法

"只有一個"是什麼意思呢?B 繼承 A,所以不是應該有 2 個myInstanceMethod 方法:帶參數與不帶參數的?



引用:
swimman寫到:
用B的myInstanceMethod(int)方法compiler在邊譯期就會檔下來,根本就進不了RUNTIME
除非強制轉型
強制轉型後就轉為RUNTIME的時期才進行檢查

請問 2 個問題:
1 是強制轉型要怎麼轉?
2 是強制轉型不會喪失多型的精神嗎?[事後補註] 此處誤以為swimman兄是在講 override


引用:
swimman寫到:
基本上函數的 OVERLOADING 並不是什麼了不起的東西
根據C++的函式語意學
C++會將函數名稱跟所使用參數加在一起成為新的函數名稱
所以函數名稱一樣參數不一樣就會變成不同的函數
所以在邊譯期就可以進行檢查知道要叫哪一個函數
這也就意味著回傳值的不同是不能構成可以辨別的新涵數
基本上OVERLOADING跟多型是沒有關係的

OVERLOADING 幾乎是每個 OO 語言的功能要求,是沒什麼了不起。
可是有點疑問的是這句:"基本上OVERLOADING跟多型是沒有關係的"。那是什麼跟多型有關係呢?我對多型的全貌並不是十分了解。[事後補註] 此處誤以為swimman兄是在講 override
我講一下我的認知: OVERLOADING 只是達到多型的一種手段,但 OVERLOADING 不代表多型的全部。不知道是否有錯。
[事後補註] 此處誤以為swimman兄是在講 override,所以應該改為Override 只是達到多型的一種手段,但 override 不代表多型的全部。


以上幾點,還請幫忙釐清觀念。:

[jocosn 在 2005-4-20 01:17 PM 作了最後編輯]
發表人: swimman    時間: 2005-4-20 09:15 AM


引用:
感謝 swimman 的解釋,小弟有幾點疑問,還請幫忙釐清:


swimman寫到:
所以就只有一個不帶參數的 myInstanceMethod 方法

"只有一個"是什麼意思呢?B 繼承 A,所以不是應該有 2 個myInstanceMethod 方法:帶參數與不帶參數的?


因為一開始宣告obj是A所以obj就是A,
Compiler不會認為obj跟B有什麼關係當然就不會有兩個方法




引用:
swimman寫到:
用B的myInstanceMethod(int)方法compiler在邊譯期就會檔下來,根本就進不了RUNTIME
除非強制轉型
強制轉型後就轉為RUNTIME的時期才進行檢查

請問 2 個問題:
1 是強制轉型要怎麼轉?
2 是強制轉型不會喪失多型的精神嗎?


強制轉型在JAVA就直接(B)obj就可以了跟C的語法是一樣的
當然不見得執行期會成功(比如說有個C繼承A而這個obj是new C();)
不過compiler認為那不是他的事了,會讓你通過編譯
是的,後期連結的確在刑別檢查上是很鬆散的
所以那是你的責任在執行期進行型別檢查後再做轉型
在某些情況下是一定要做這種轉型




引用:
swimman寫到:
基本上函數的 OVERLOADING 並不是什麼了不起的東西
根據C++的函式語意學
C++會將函數名稱跟所使用參數加在一起成為新的函數名稱
所以函數名稱一樣參數不一樣就會變成不同的函數
所以在邊譯期就可以進行檢查知道要叫哪一個函數
這也就意味著回傳值的不同是不能構成可以辨別的新涵數
基本上OVERLOADING跟多型是沒有關係的

OVERLOADING 幾乎是每個 OO 語言的功能要求,是沒什麼了不起。
可是有點疑問的是這句:"基本上OVERLOADING跟多型是沒有關係的"。那是什麼跟多型有關係呢?我對多型的全貌並不是十分了解。
我講一下我的認知: OVERLOADING 只是達到多型的一種手段,但 OVERLOADING 不代表多型的全部。不知道是否有錯。


OVERLOADING基本上跟多型沒關係
你要OVERLOADING幾個同名的FUNCTION
你就必須實做幾個FUNCTION
這個跟OO一點關連都沒有(c++可以寫出一個程式完全沒有CLASS確有OVERLOADING的函式)
基本上跟OPERATION OVERLOAD有點像都只是語法的糖衣
OVERLOADING只是讓你少背了幾個函示的名稱
用的時候比較方便
試想
沒有overloading
class a{
void f(void){}
int f1(int i){return i;}
double f2(double d){return d;}

public static void main(string[] args){
f();
int i=f1(1);
double d=f2(1.0);

}
}

有overloading

class a{
void f(void){}
int f(int i){return i;}
double f(double d){return d;}

public static void main(string[] args){
f();
int i=f(1);
double d=f(1.0);

}
}
發表人: jocosn    時間: 2005-4-20 01:06 PM

感謝 swimman 兄的幾點觀念,但是我感覺我誤解 swimman 兄的意思。小弟提出幾個看法

引用:
基本上OVERLOADING跟多型是沒有關係的

對不起,就是這句話,此處是寫 OVERLOADING ,一時不查以為是 override。所以我全面的留言有錯誤,我等會去改過來加註。
我的程式碼是因為看不小神童在問什麼,所以用到 OVERLOADING,完全是個錯誤的範例,造成誤解請見諒。


引用:
c++可以寫出一個程式完全沒有 CLASS 確有 OVERLOADING 的函式

個人補充:
確實如此,如果大家還沒忘記的話,因為 C++ 要考慮 C 語言的相容性, C 是個 OO 的語言嗎?不是。但是 C++ 進一步提供 OO 的功能,因為 C++ 是一個多種設計思維面考慮的語言,你可以寫一個完全不 OO ,或完全 OO 的語言。你可以寫一個完全沒有 class 的程式,但是可以跑,但是這種程式絕對沒有多型的功能
今天,一個沒有 CLASS 但確有 override 的函式,在 java, C# 上都不可能出現。所以不能說 override 跟多型沒有關係。因為沒有 override,就沒有多型,但是有了 override,不一定就會有多型。

[jocosn 在 2005-4-20 01:24 PM 作了最後編輯]
發表人: Acute    時間: 2005-4-20 05:08 PM


引用:
jocosn寫到:
我的程式碼是因為看不小神童在問什麼,所以用到 OVERLOADING,完全是個錯誤的範例,造成誤解請見諒。


呵, 我都沒問啥阿, 我只是說, 那個描述是有問題的, 如此而已哩

Acute.
發表人: jocosn    時間: 2005-4-20 07:39 PM


引用:
Acute寫到:

引用:
jocosn寫到:
我的程式碼是因為看不小神童在問什麼,所以用到 OVERLOADING,完全是個錯誤的範例,造成誤解請見諒。


呵, 我都沒問啥阿, 我只是說, 那個描述是有問題的, 如此而已哩

Acute.


就是因為沒問啥,所以不知道要答啥?
發表人: Acute    時間: 2005-4-20 11:13 PM


引用:
Acute寫到:

引用:
jocosn寫到:
那應該怎麼改才對?


2. 多型在程式編譯時期利用判斷訊息參數的類型與個數來決定運作的方法。

應該這樣子, 比較合理 ^^"

Acute.


忘了說, 上面的說法, 是為了彰顯原文這方面的描述不太對勁, 所以, 才會寫上 "XX時期"

就語言定義而言, 基本上, 很少會去描述一個動作應該怎樣做, 也就是, 語言定義裏面, 頂多是寫成 (甚至於很可能不寫, 因為沒必要規定作法):
多型利用判斷訊息參數的類型與個數來決定運作的方法。

實際上如何實作, 則由製作compiler 的人去根據合適的方法達到目標

補述:
通常會出現"結果論" 或"推測論", 都是由其他介紹相關語言之書籍的作者寫進去的.
所謂結果論, 是指, 根據某個或大多數compiler 作法, 而把該作法加入語言介紹中, 變成一個雖然沒錯, 但是不適當的描述.
所謂"推測論", 也是其他人寫語言介紹書時寫進去的, 但是, 因為該作者可能根本不懂compiler 該怎麼做, 只好胡思亂想隨便猜. 個人推測(我也在亂猜), 原文的第二點, 就是作者的"推測"結果, 只是, 該推測結果, 是無法做到的, 呵

一般而言, 真要了解一個語言, 要直接看語言定義的書籍, 這種書, 通常只有一本(俗稱:Bible), 而且, 是由語言定義者直接撰寫出來的. 以C 而言, 就是K&R 親手撰寫的The C programming language. 以C++ 而言, 就是The C++ programming language. (作者我忘了是誰) 用這種書籍當學習語言的入門會很辛苦, 因為書籍的目的是詳盡的介紹語言, 而不是教導如何學習該語言, 但是, 當你真想學好一個語言, 你就是必須花過一次時間, 把bible 仔細研讀一次, 這樣子, 你才能真正了解該語言, 並且不會被曾經看過的書誤導.

Acute.
發表人: ecity    時間: 2005-5-17 05:01 PM

看了各位大大的討論, 小弟也來發表一下自己的拙見.

1. Polymorphism
    一個Object可以在Runtime時轉換為不同的Class Type(即其Implement的Interface及Super Class), 而其真正的Type是其被instance化時的Class. 通常會在開發比較底層的程式時會用到許多這方面的技巧(例如:Framework), 而Design Pattern內也大量運用這種觀念.

2. Overloading
    一個Method具有同名稱但是可以傳入不同型態的變數, 例如Java的System.out.println即是一個Overloading的標準例子.

3. Overriding
    當subclass繼承super class時, 為了能有不同的行為, 此時會改寫super class的Method, 但構成Overriding的條件是要相同名稱, Argument List及Return Type.




歡迎光臨 TWed2k (http://twed2k.org/) Powered by Discuz! 4.1.0