作者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/cn.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