作者berice152233 (WASHI)
看板C_Sharp
標題[問題] 請教向上/向下轉型的問題
時間Thu Nov 21 17:31:10 2019
各位學長好
我在看深入淺出C#的時候有一個疑問
第一版(買的時候沒注意...)
P267、P268的部分有談到向上、向下轉型
就我個人的理解
例如父類有A方法,子類有B、C方法
向上轉型:
將子類別的物件內容等同於父類
父類名 物件1 = new 子類名();
原本子類物件可以使用A、B、C方法
向上轉型後的物件1就只能使用父類的A方法
向下轉型:
將向上轉型的物件,用一個新物件再轉回來
上面的子類物件現在只能用A方法
那我再用一個物件讓他轉回來(???)
子類名 物件2 = 物件1 as 子類名;
這樣物件2就能使用A、B、C三種方法
在這裡我就有問題了
為什麼要這樣向上向下轉型?
如果直接new一個新的父類物件
效果不就等同向上轉型後的物件嗎?
如果直接new一個新的子類物件
效果不就等同向下轉型後的物件嗎?
有什麼情況非得要用向上、向下轉型不可呢?
請各位學長不吝指教,感謝
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 59.125.120.238 (臺灣)
※ 文章網址: https://webptt.com/m.aspx?n=bbs/C_Sharp/M.1574328676.A.449.html
1F:推 s4300026: 不,你搞錯了,真相只有一個,就是實體只有一個。其他 11/21 18:21
2F:→ s4300026: 都是標籤紙,is是判斷能不能把標籤貼在實體上,as是回 11/21 18:21
3F:→ s4300026: 傳一個已經貼在上面,並且標籤名稱是你指定的。 11/21 18:21
4F:推 s4300026: 實體就是你new出來的東西,new回傳的東西也是標籤紙。 11/21 18:26
5F:→ s4300026: 然後第三句話,標籤名稱要改成標籤型態。 11/21 18:27
感謝S大的標籤紙說明讓我多了些想法
我又再研究了一下:
父類別 物件1 = new 子類別();
這樣會產生一個名為 物件1 實體
之後再
子類別 物件2 = 物件1 as 子類別;
在這裡 物件2 其實就是 物件1
只是貼上了 物件2 的標籤
於是就產生出和 物件1 相同內容的 物件2
但差別 物件2 可以使用子類別方法
因為他已經被貼上子類的標籤
同時,如果用 物件2 去改變子類的屬性時
物件1 也會受到影響,因為是同一個實體
這樣的理解正確嗎?
6F:推 s4300026: ================= 11/21 18:31
7F:推 s4300026: 那為什麼要向上轉型,因為你很懶,當你有一堆子類別時, 11/21 18:40
8F:→ s4300026: 你不想要宣告一堆變數去記住實體在哪,父類別都可接, 11/21 18:40
9F:→ s4300026: 還可以直接用爸爸的方法,當你真的要用兒子的方法時,再 11/21 18:40
10F:→ s4300026: 向下轉型就好了。 11/21 18:40
11F:→ berice152233: 感謝,有點複雜,我會努力理解的 11/21 22:45
12F:推 samchung: 推s大的標籤紙形容 XD 11/21 23:18
13F:→ samchung: 小弟想到物件集合(或物件陣列)的應用情況 11/22 00:33
15F:→ samchung: 關鍵在泛型集合使用父類別的型別 11/22 00:34
16F:→ samchung: 才可在集合內放入相同血緣關係的父、子物件 11/22 00:34
17F:推 Litfal: 標籤紙讚讚 至於為什麼要轉, 得從OOAD最基本的收納與使用 11/22 09:15
感謝各位學長的回答
大概是因為我還沒開始寫很長的程式
所以還搞不太懂上下轉型的重要性
目前看起來是要節省寫程式時的麻煩
還有增加閱讀性?
※ 編輯: berice152233 (59.125.120.238 臺灣), 11/22/2019 10:08:47
18F:→ Litfal: 來想。你有一些鉛筆和一個鉛筆盒,鉛筆盒只能放鉛筆,那你 11/22 09:22
19F:→ Litfal: 拿到原子筆時就會有點麻煩。你有兩個選擇:1.做一個原子 11/22 09:22
20F:→ Litfal: 筆盒拿來放原子筆。2.把鉛筆和原子筆都視為筆,並把鉛筆和 11/22 09:23
21F:→ Litfal: 改成筆盒,可以放所有種類的筆。 盒 11/22 09:23
22F:推 Litfal: 想當然是2.比較好,你也不想包包裡塞滿各種類的筆盒吧? 11/22 09:27
23F:→ Litfal: 而且未來有其他種類的筆,也是直接塞進筆盒裡就好。 11/22 09:28
24F:推 Litfal: 這是收納部分。而使用上,管他什麼筆,都可以用來寫 11/22 09:31
25F:→ Litfal: 所以會在父項 筆 的類別裡面,定義 寫() 的方法 11/22 09:33
26F:→ Litfal: 你從筆盒裡面拿出的筆,管它是什麼筆,拿出來就可以寫() 11/22 09:33
27F:推 Litfal: 至於各種筆自己獨特的功能,例如多色筆可以換色,自動筆可 11/22 09:36
28F:→ Litfal: 以換筆芯,鉛筆可以被削,這些功能就由子類別個別去實作 11/22 09:36
29F:推 Litfal: 向下轉型的需求就由此而來。例如你有台削鉛筆機,它只吃鉛 11/22 09:40
30F:→ Litfal: 筆。原本隨便從鉛筆盒拿出一支筆都能削,現在,你必須檢查 11/22 09:42
31F:→ Litfal: (或是由削鉛筆機檢查)你從筆盒拿出的筆,它是不是鉛筆, 11/22 09:42
32F:→ Litfal: 確定是鉛筆後才能把它塞給削鉛筆機來削 11/22 09:42
感謝L大的說明,這個例子也很好懂
稍微能對as的應用有具體的想像了
※ 編輯: berice152233 (59.125.120.238 臺灣), 11/22/2019 10:12:08
33F:推 s4300026: 實際上標籤紙的概念是出於 深入淺出 C#,也就是你正在 11/22 10:55
34F:→ s4300026: 讀的那本,那本書上的圓圈就是實體,方框內的名稱就是 11/22 10:55
35F:→ s4300026: 標籤。 XD 11/22 10:55
對,我也是看了你的說明之後往前翻
就有種恍然大悟的感覺,哈哈
36F:→ s4300026: 實際上,在實務上只有強調轉型,我們並不在乎是 “向上 11/22 10:55
37F:→ s4300026: 還是向下轉型”,在後面的章節,interface的關鍵字,你 11/22 10:55
38F:→ s4300026: 就會體會到了。 11/22 10:55
那我就期待看到這邊了
※ 編輯: berice152233 (59.125.120.238 臺灣), 11/22/2019 11:15:53
39F:推 s4300026: 回頭看了你的敘述,在你的回覆中,“於是就產生出和 物 11/24 09:36
40F:→ s4300026: 件1 相同內容的 物件2”,這段敘述是錯誤的,所謂的 “ 11/24 09:37
41F:→ s4300026: 產生”,就是new,這是錯誤的理解。 11/24 09:37
42F:推 s4300026: 正確的理解是:Parent A = new Son(); //產生一個子類別 11/24 09:40
43F:→ s4300026: 實體,然後把父類別標籤貼上去 11/24 09:40
44F:推 s4300026: 標籤名稱為 A。 if(A is Son) Son B = A as Son。 如果: 11/24 09:54
45F:→ s4300026: 標籤A所貼的實體 可以被當成 子類別,則:標籤A所貼的實 11/24 09:54
46F:→ s4300026: 體 請把他當成 子類別 看待,然後我把 子類別 的標籤貼 11/24 09:54
47F:→ s4300026: 上去,標籤名為B。 11/24 09:54
48F:→ s4300026: A = new Parent(); 然後,我把標籤紙A “改貼在” 新的 11/24 09:59
49F:→ s4300026: 父類別實體上。 11/24 09:59
阿...原來是貼上父類標籤的子類實體
經你這麼一說我對於實體的概念不太明確
感謝解說
※ 編輯: berice152233 (59.125.120.238 臺灣), 11/26/2019 13:19:06
50F:推 nickboy: 我基本上都用向下居多,向上是懶惰的時候才會用 12/06 17:07