伊莉討論區

標題: [求助]請問一個關於繼承-遮蔽的問題[已解決] [打印本頁]

作者: ahway9988    時間: 2018-11-14 04:11 PM     標題: [求助]請問一個關於繼承-遮蔽的問題[已解決]

本帖最後由 ahway9988 於 2018-11-16 02:35 PM 編輯

我想用多形方法以父類去取得子類的成員變數,若不使用方法去取得子類成員變數,是不是就沒有別的方法去取得了嗎?
求大大們解惑QQ


以下例子因為發帖似乎被告知出現敏感字眼,於是用圖片方式呈現,不便見諒orz)


[attach]125568459[/attach][attach]125569123[/attach]
.文件內容:[attach]125568470[/attach]

.
[attach]125592927[/attach]
文件:[attach]125592952[/attach]






補充內容 (2018-11-16 02:37 PM):
加外想知道 有沒有人知道 我的內容哪個部份被判定為敏感字眼被遭拒貼文orz
作者: codewice    時間: 2018-11-15 01:41 AM

你可以強制把父類別轉型成子類別,但是這樣就失去多型的意義了。
  1. System.out.println(((PlanetBase.BedRoom)bases[0]).file);
複製代碼
你現在的寫法,看起來有點像是,為了過編譯器的檢查而硬寫出來的。譬如說 bedroom 跟 restaurant 可以變成 static class,也不需要放在 PlanetBase 裡面。但這部分就離題了,暫且不談。

多型目的就是希望其他部分的邏輯,只要針對父類別去寫程式就好,盡量忘記子類別的存在。所以才會在父類別訂出抽象方法,由子類別實作。如果你希望在程式中直接存取到子類別的成員,亦即,程式要能夠察覺到子類別的存在,並確定某一個 instance 就剛剛好是那個子類別。

在這種情況下,我們會使用強制轉型 cast。但是對於 Java 這種強型別的語言,使用強制轉型就是在削弱 Java 的優勢,所以實務上會盡量避免 cast。

作者: kwj    時間: 2018-11-15 12:46 PM

個人認為這其實是 design pattern 的問題,也就是當你嘗試這麼做的時候,這麼做帶來的優點應該要符合你的目的。

通常我們使用封裝技巧時,就是想要隱藏細節,所以原則上會這麼做的目的應該要是隱藏 bedroom 和 restaurant 的 file 相關操作細節。也就是說在這個前提之上,本來就不應該存在想要直接存取 file 變數的需求,因為那就是使用這種 design pattern 時意圖想藏起來的目標。反過來說,如果真的有意想讓外部 class 直接存取 file 變數,那麼一開始就不應該採取這種 design pattern 了。
作者: ahway9988    時間: 2018-11-16 09:48 AM

本帖最後由 ahway9988 於 2018-11-16 09:51 AM 編輯
codewice 發表於 2018-11-15 01:41 AM
你可以強制把父類別轉型成子類別,但是這樣就失去多型的意義了。你現在的寫法,看起來有點像是,為了過編譯 ...

靜態方法 ,我懂了,先前沒想到,因為是想讓相類似的東西放在同一頁面裡,所以刻意弄出個PlanetBase
強制轉型 ,OK 我也懂了,知道它的型別後再強制轉型,
其實一來我只是好奇想知道有沒有解,二來當初 那些類是test的,所以為了偷一點懶這樣做XD

作者: ahway9988    時間: 2018-11-16 09:52 AM

kwj 發表於 2018-11-15 12:46 PM
個人認為這其實是 design pattern 的問題,也就是當你嘗試這麼做的時候,這麼做帶來的優點應該要符合你的目 ...

嗯 沒錯 是我設計模式的問題 ,當初 那些類是test的,所以為了偷一點懶這樣做XD
因為感覺直接存取 比跟 再為它們多設一道方法 簡單快迅多了XD
作者: kwj    時間: 2018-11-16 11:02 AM

本帖最後由 kwj 於 2018-11-16 11:04 AM 編輯
ahway9988 發表於 2018-11-16 09:52 AM
嗯 沒錯 是我設計模式的問題 ,當初 那些類是test的,所以為了偷一點懶這樣做XD
因為感覺直接存取 比跟 再 ...

這要回歸到 design pattern 的原意了。

舉例來說,「十年經驗與一年經驗的程序員的區別」這篇文章不知道樓主看過沒有~。為什麼在一年到五年的期間,要寫出一樣的東西,程式設計師會嘗試寫得越來越複雜呢?通常問題在於想解決的問題並不是「現在寫得更快」,而是「未來需要修改時改得最少」。

PS. 而到了十年的時候又反璞歸真,這部份我個人認為是過度設計產生的問題。

回到 design pattern 來,我個人對於 design pattern 的看法是~每一種 design pattern 都有嘗試想要解決某一種問題,但同樣會帶來其他問題(最基本的就是會需要多寫一些直觀來看好像可以不需要的程式碼)。要選擇使用 design pattern 時,每次都需要思考這麼做對於現在面對的問題是好是壞、有沒有必要。例如對於一個寫完以後幾乎不會修改、不會擴充,或者每次需要修改時大概現在寫好的東西都可以廢棄掉等等,這類狀況就根本無須浪費時間寫 design pattern,因為 design pattern 給予的靈活性完全用不到。

對於樓主的狀況,因為這些程式碼也只是寫來測試用的,所以這些程式碼寫完就會廢棄,既不可能需要維護它、也不會有未來擴充的需求。那麼顯然在這種狀況下,用 design pattern 來寫自然是會顯得浪費時間了。
作者: ahway9988    時間: 2018-11-16 11:46 AM

kwj 發表於 2018-11-16 11:02 AM
這要回歸到 design pattern 的原意了。

舉例來說,「十年經驗與一年經驗的程序員的區別」這篇文章不知道 ...

感謝大大的解惑,我又多懂了一些概念了QQ
其實我雖然有VB的底 才剛接觸到java,之前VB的基礎完全無法跟java比orz
java的功能確實很強大
所以我即興奮又害怕難以駕馭它們,遇到一點小小問題,我就想求到各種可能性或替代方法

正式設計上我想還是尊從用get 、set 去存取比較好 ,不然總是會遇到一些自己難以預料的問題orz
作者: codewice    時間: 2018-11-17 11:21 PM

本帖最後由 codewice 於 2018-11-20 08:31 AM 編輯
ahway9988 發表於 2018-11-16 09:48 AM
靜態方法 ,我懂了,先前沒想到,因為是想讓相類似的東西放在同一頁面裡,所以刻意弄出個PlanetBase
強制轉型  ...

其實靜態方法(static method)跟靜態型別(static class)兩者是不一樣的概念,不過按部就班地學就好。現在還不用一口氣把事情搞得那麼複雜,先把基礎的繼承跟多型多寫幾次之後,再研究 static 就好。

「知道它的型別後再強制轉型」,是的。只要知道型別後,強制轉型,就可以做到你原來的疑問「不使用方法去取得子類成員變數」。但是,實務上我們會盡量避免「知道子類別究竟是什麼型態」

譬如說你現在想寫一個模擬器大集合的程式,所以定義了一個抽象 class 叫 Emulator (下面這個例子可以寫成 interface,但我們還不要管它)
  1. abstract class Emulator {
  2.     abstract public String getName();
  3.     abstract public void runGame(File rom);
  4. }
複製代碼
底下不管是要接任天堂模擬器還是 PS 模擬器,你的主程式都能確保兩件事情 1) 實作的模擬器會告訴你,它的名字 2) 它能夠執行遊戲。所以你的主程式,只要知道這兩個假設就好了。

未來你想要增加新主機的模擬器,只要實作這兩個介面就可以順利接上主程式。

但是反過來,如果你的主程式對於 Emulator 的子類別,有愈多的預期 (好比,會把某一個 Emulator 強制轉型成 NesEmulator,然後叫它做一些任天堂模擬器專屬的事情),那麼你的主程式在未來的擴充上,就會增加難度。

所以有句話是「要針對介面寫程式」。

如果已經結束了語法層次的學習,開始進入物件導向的階段,可以去看看「深入淺出設計模式」,應該會有些幫助。


補充內容 (2018-11-20 08:29 AM):
抱歉我後來想起來不是 Head First Java, 應該是 Head First Design Patterns (深入淺出設計模式)




歡迎光臨 伊莉討論區 (http://a401.file-static.com/) Powered by Discuz!