伊莉討論區

標題: 有關java抽象問題 [打印本頁]

作者: b2581167    時間: 2018-4-23 06:45 PM     標題: 有關java抽象問題

提示: 作者被禁止或刪除 內容自動屏蔽
作者: johnwanz    時間: 2018-4-24 08:48 AM

繼承(Inheritance)的目的應該是為了多型(Polymorphism). 沒有寫到背景, 所以不知道是在什麼狀態下. 如果是在學習過程, 或許是在教授抽象函式的作法, 也或許是課程為了後續教學的鋪墊.

抽象類別及抽象函式的作用, 是在繼承體系中, 避免實做個體差異化的方式; 需要差異化的部分, 則由繼承子類別來實作. 父類別不需要預先寫好其中任何一種作法(抽象化, 僅保留共同部分).

一方面可明確告知子類別需要實作, 另一方面, 使用的人不需要再費心去看去猜(封裝), 差異化部分在父類別做了什麼, 是否需要重新定義(override).

實務上, 沒有需要多型的時候, 通常不建議使用繼承, 可避免未來維護不易. (如果需要)

如有訛誤, 請各位指正, 謝謝~
作者: codewice    時間: 2018-4-25 10:53 PM

我覺得樓上講得很好了,只是多做一點補充,希望可以讓你更理解 johnwanz 說的東西

先講 abstract 的影響

當一個 class 被宣告成 abstract 的時候,我們不能直接用 new 來產生一個 instance。abstract 等於是告訴 compiler 說:「這個 class 我實作了一部份,但是也有一部份我現在還沒有想法不知道該怎麼做,先等等吧」,class 裡面用 abstract 修飾的 method 就是還沒做完的部分,以你的例子來說就是 `abstract float size();`

那它在設計上會有什麼用處呢?以 Java 裡面的 InputStream 來說,它就是一個 abstract class,裡面有個抽象方法叫 `read()`。你沒有辦法直接產生一個 InputStream,因為 InputStream 並沒有決定該怎麼做 read()

InputStream 有許多子類別,好比讀檔案的 FileInputStream 或是用來讀 byte 陣列的 ByteArrayInputStream,前者你可以接上一個檔案產生 instance,後者你可以塞進一個 byte array 來產生 instance。而這兩者都是 InputStream 的子類別,所以你在後續的程式碼就可以說「我不管你是什麼 InputStream,反正你 InputStream 就對了,所以我可以呼叫你的 read() 來讀東西」

如果回到你的範例,把 abstract 有關的都拿掉,的確可以 compile 過。但是程式繼續寫下去,當你想要呼叫 size() 的時候,compiler 會說「round 不知道 size() 是什麼東西」,於是你變得一定要用到子類別的 redball 而非父類別的 round。

改一下程式碼的確還是可以運作,只是這樣在未來,抽換底層元件的彈性就變差了。就像我們組裝電腦,主機板如果只預期「給我一顆 SATA 硬碟」那很好辦事,想換什麼硬碟都行;但如果指定要某個牌子某個尺寸的 SATA 硬碟,換硬碟就會麻煩許多。

所以在後續的程式碼,通常會鼓勵盡量針對 round 這個父類別去寫邏輯就好,盡量忘記子類別 redball 的存在。
作者: theloserbm    時間: 2018-4-27 02:54 PM

樓上已經把abstract class的功用講得滿清楚的.

關於減少程式碼的部分, 如果單單看abstract class本身和他的字類別, 其實程式碼是變多了. 減少的部分其實是呼叫abstract class的地方

假設說有一個地方需要判斷類別做一些事, 可以這樣寫
if (shape instanceof round)
  // do something
if (shape instanceof triangle)
  // do something

而不需要寫
if (shape instanceof redball || shape instanceof blueball || ...)

而且當你以後新加一個種類的round如greenball, 也不需要更動這一部分的代碼. 這個方法在interface上面是很常用的.

至於加入abstract在父類別主要是用來避免別人直接new, 因為直接new了裡面也沒有東西可以用, 有很大機率會出錯.


作者: johnwanz    時間: 2018-4-30 09:02 AM

例子是為了說明多型嗎? 我的認知好像有點差異.

我的想法是類似這樣,
* Class有個abstract function move. 子類來繼承, 並實作move.
* 某程式會以abstract class來操作不特定子類, 當遇到需要移動時, 直接呼叫move function.
* 不再需要 if...else...
  1. // 概念如下
  2. main(){
  3. ...
  4. objectA create from subclass
  5. ...
  6. funcA (objectA)
  7. ....
  8. }

  9. function funcA(abstract class objB){
  10.   ...
  11.   objB.move() // I don't care who it is.
  12.   ...
  13. }
複製代碼

作者: zaq12345    時間: 2020-4-4 12:29 AM

我覺得良葛格的解釋也很清楚....
openhome.cc/Gossip/JavaGossip-V1/AbstractClass.htm

可以參考一下....




歡迎光臨 伊莉討論區 (http://web01.eyny.com/) Powered by Discuz!