C_Sharp 板


LINE

你这样写会让其他人乱用继承关系。 原PO的解答的确是要用多型,Abb大写的没错。 但是「如何写」是一回事, 你有用到DesignPattern的概念,写出来的东西却打了自己一巴掌。 ====文字档==== 文字档Father.txt Father My name is Darth Vader. I am your Father! 文字档Son.txt Son My name is Luke Skywalker. No~~~~~~~~~! ====程式码==== 程式码Family.cs abstract public class Family { public string StrA { get; set; } public string StrB { get; set; } public Family(StreamReader reader) { this.StrA = reader.ReadLine(); this.StrB = reader.ReadLine(); } public abstract void ShowStrA(); public abstract void ShowStrB(); } 程式码Father.cs public class Father : Family { public Father(StreamReader reader) : base(reader) { } public override void ShowStrA() { Console.WriteLine(this.StrA); } public override void ShowStrB() { Console.WriteLine(this.StrB); } } 程式码Son.cs public class Son : Family { public Son(StreamReader reader) : base(reader) { } public override void ShowStrA() { Console.WriteLine(this.StrA); } public override void ShowStrB() { Console.WriteLine(this.StrB); } } 程式码FamilyFactory.cs public class FamilyFactory { public static Family CreateFamily(string familyMember, StreamReader reader) { if (familyMember == "Father") { return new Father(reader); } else if (familyMember == "Son") { return new Son(reader); } else { return null; } } } 客户端调用 StreamReader reader1 = new StreamReader("Father.txt"); StreamReader reader2 = new StreamReader("Son.txt"); string familyMember1 = reader1.ReadLine(); string familyMember2 = reader2.ReadLine(); Family family1 = FamilyFactory.CreateFamily(familyMember1, reader1); Family family2 = FamilyFactory.CreateFamily(familyMember2, reader2); family1.ShowStrA(); family2.ShowStrA(); family1.ShowStrB(); family2.ShowStrB(); 结果 My name is Darth Vader. My name is Luke Skywalker. I am your Father! No~~~~~~~~~! Father类别或Son类别是不同的, 只有新手或不熟悉物件导向的人才会直接用Son来继承Faher, 这两个类别都应该抽像於Family类别, 这样子写才比较好维护也有弹性。 Abb大说的多型是这样, 只不过我偷懒把strA跟strB的readline写在建构式。 ※ 引述《adrianc (123)》之铭言: : 看完後整整十分钟心神不宁无法继续工作,决定趁吃饭前回一下。 : 由原PO回文中已知两个类别是继承关系。 : 依照原文推文中的Abb大建议,实作程式码。 : // 以下程式码依原程式内容 : // 预期档案第一行可能读到 "father" or "son" 之外的内容,且不须处理 : // 变数命名使用原程式命名方式 : private void button1_Click(object sender, EventArgs e) : { : System.IO.StreamReader file = new System.IO.StreamReader("file.txt"); : string str = file.ReadLine(); : ClassFather xxx = null; : if (str == "father) : { : xxx = new ClassFather(); : } : else if (str == "son") : { : xxx = new ClassSon(); : } : if (xxx != null) : { : xxx.strA = file.ReadLine(); : xxx.strB = file.ReadLine(); : } : } : --------------------------------------------------------------- : ClassFather xxx = null; : . : . : . : xxx = new ClassSon(); : } : 这段视你的需求可以考虑用 : ClassFather xxx = FatherSonClassFactory.Create(str); : 来替换掉 : 然後 C# (物件导向) 的 method 主要功能应该不是用来排版.. : ※ 引述《LetsGoToEat (一起去吃东西吧)》之铭言: : : 感谢帮忙,我试着改成这样 : : private void button1_Click(object sender, EventArgs e) : : { : : System.IO.StreamReader file = new System.IO.StreamReader("file.txt"); : : string str = file.ReadLine(); : : if (str == "father") : : { : : ClassFather xxx = new ClassFather(); : : IamFunction(file, xxx); : : } : : else if (str == "son") : : { : : ClassSon xxx = new ClassSon(); : : IamFunction(file, xxx); : : } : : } : : private void IamFunction(System.IO.StreamReader file, ClassFather xxx) : : { : : xxx.strA = file.ReadLine(); : : xxx.strB = file.ReadLine(); : : } : : 似乎是可以了@@ --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 60.249.117.38
※ 文章网址: http://webptt.com/cn.aspx?n=bbs/C_Sharp/M.1400480064.A.F24.html ※ 编辑: StupidGaGa (60.249.117.38), 05/19/2014 14:17:48
1F:推 adrianc:你要不要看一下原po回文的 IamFunction 方法签名 05/19 14:48
2F:→ adrianc:再想想为什麽这样写? 这样看不懂我也不解释了 05/19 14:49
3F:→ adrianc:另外 这边的抽象物件 (Father也好 Family也好) 05/19 14:50
4F:→ adrianc:认识 StreamReader 本身就是..嗯..所谓的"新手"写法了.. 05/19 14:52
我已经说过,我偷懒写在建构式里面, streamReader要拔掉没差,重点是观念, 类别本来不应该继承类别, 类别是要继承於抽像类别或介面。 继承的观念是is,难道你会说son is father? 为什麽我要father跟son抽像,然後都继承family? 因为实作跟维护上我看过太多人都乱继承, 如同你写的范例,son继承於father,这是不对的写法。 如果你有去了解DesignePattern, 你会了解为什麽son跟father要继承於family。 ※ 编辑: StupidGaGa (60.249.117.38), 05/19/2014 15:01:20
5F:→ adrianc:基本上 这个案例根本牵扯不上 DesignPattern 所以 05/19 14:56
6F:→ adrianc:我还特别在原范例中跳过 Factory 以免模糊焦点 05/19 14:57
就算不管DesignPattern, 我还是那句话, 类别不该继承於类别, 类别应该继承於抽像类别或介面。 ※ 编辑: StupidGaGa (60.249.117.38), 05/19/2014 15:05:24
7F:→ adrianc:我还真闲... 1. 不知道你是不是看出原po"已经"继承类别了 05/19 15:23
8F:→ adrianc:2. 如果用偷懒解释的话 那所有的 dirty code 都是合理的 05/19 15:24
9F:→ adrianc:我们也不需要再往下讨论了 05/19 15:24
10F:→ adrianc:3. 我不知道 "son is father" 成不成立 至少已知资讯中 05/19 15:25
11F:→ adrianc:没有超能力是看不出来的 我只能从物件行为判断 05/19 15:26
12F:→ adrianc:4. 物件导向设计原则中 只有依赖倒转原则 05/19 15:32
13F:→ adrianc:但没有一条告诉你 "类别不该继续於类别" 05/19 15:33
14F:→ adrianc:需要从framework找些 "类别继承类别的"例子给您吗? 05/19 15:33
15F:→ adrianc:5. again "我写的范例"中 没有包括 son 继承 father 05/19 15:36
※ 引述《adrianc (123)》之铭言: : ClassFather xxx = null; : if (str == "father) : { : xxx = new ClassFather(); : } : else if (str == "son") : { : xxx = new ClassSon(); : } 你的程式码, 如果son没继承於father, 请问如何写出 ClassFather xxx = new ClassSon(); ? 这段我跑起来跟本不行, 如果可以的话麻烦让我看一下, 先不管谁写的怎样,我对这段写法很感兴趣,希望你可以教我这段。 : ※ 引述《LetsGoToEat (一起去吃东西吧)》之铭言: : : private void button1_Click(object sender, EventArgs e) : : { : : string str = file.ReadLine(); : : if (str == "father") : : { : : ClassFather xxx = new ClassFather(); : : IamFunction(file, xxx); : : } : : else if (str == "son") : : { : : ClassSon xxx = new ClassSon(); : : IamFunction(file, xxx); : : } 原PO的, 他很清楚知道Father跟Son不同的类别。
16F:→ adrianc:真的要说 了不起是"偷懒" 延用了既有类别 05/19 15:37
17F:推 adrianc:最後 用抽象隔离实作是个好的习惯 但不代表永远可以拿 05/19 15:42
18F:→ adrianc:一句话就说别人写错 (更何况这句话本身就有问题) 05/19 15:43
19F:→ adrianc:不然 你直接批我变数用 xxx strA 会不会比较快? 05/19 15:44
framwork有类别继承类别,这我之前就看过,但它写的我不认为有错, 因为framwork的继承很明显是is的关系。 要笔战也很无聊,而且比这根本没意义, 单纯看到问题就点出,没啥意思, 另外,谢谢提醒streamReader的问题,写的时候的确没想到。 另外, 可以的话麻烦告诉我,不用继承的话如何写出这段, ClassFather xxx = new ClassSon(); 这段我承认我看不懂。 ※ 编辑: StupidGaGa (60.249.117.38), 05/19/2014 16:16:38
20F:→ adrianc:话说大哥 你看到 IamFunction 的签名了没? 05/19 16:20
21F:→ adrianc:你是没看到还是真的看不懂? 05/19 16:21
22F:→ adrianc:那个签名已经知道他的 son 有继承 father 了.... 05/19 16:22
23F:→ adrianc:还是看不懂签名? signature? 05/19 16:23
那段看过了, 原PO没意外是有用继承。 但你写的范例如果没用继承的话,我也跑不起来。 你也说你写的范例中没有包括son继承father, 所以你写的范例son有没有继承faher? 如果有,你自己也清楚这样范例不太好, 如果没有,就很奇怪了。 ※ 编辑: StupidGaGa (60.249.117.38), 05/19/2014 16:28:56
24F:→ adrianc:你不觉得msdn有错 却觉得这里的Son继承Father 有错 理由? 05/19 16:25
25F:→ adrianc:不要问这麽大的好了 这里的son和father各是什麽类别 05/19 16:26
26F:→ adrianc:你知道吗? 我不清楚 因为就我看到的内容为限 只看到属性 05/19 16:27
27F:→ adrianc:所以 以内容为限 son继承father 可能有错 也可能没错 05/19 16:29
28F:→ adrianc:所以在没有更多已知的情况下 我觉得你的指教很无厘头 05/19 16:30
29F:→ adrianc:上面写的5刚好被你的补充切成两段 05/19 16:33
30F:→ adrianc:"我写的"范例中不包括继承 但我有延用"既有的"类别 05/19 16:34
31F:→ adrianc:也就是说 这是一段不改变类别设计为前提的范例 05/19 16:34
32F:→ adrianc:不改变设计的原因是 以目前看到的内容为限 05/19 16:39
33F:→ adrianc:没办法判断 son和father 的继承关系是不是合理 05/19 16:40
34F:→ adrianc:言归正传 原PO的问题是要避免重覆程式码 05/19 16:43
35F:→ adrianc:结果改完後在 if 和 else 中都出现了都样的呼叫 05/19 16:43
36F:→ adrianc:既然都已经继承了 所以我单纯写出一点修正来避开这个问题 05/19 16:45
37F:→ adrianc:完全看不出你回一篇文在激动什麽 DesignPattern 的 = = 05/19 16:46
38F:→ adrianc:如果你还是觉得这个例子中是错的 麻烦帮我 05/19 16:54
39F:→ adrianc:把son/father换成label/control, strA/strB换name/text 05/19 16:55
40F:→ adrianc:再帮忙写个信问MS 为什麽Label可以继承非抽象类别Control 05/19 16:56
你的例子举错了, 为什麽我会说MS类别继承类别我认同, 是因为他的继承有is的关系在, label is control,form is control,这种继承是OK的, (labal是控制项,from是控制项。) 反过来看, father跟son单就类别名字来看不太是is的关系, 难道你会认为,你是你父亲? 难道你会认为,label is form? 你可以看看下列描述, 1. 儿子是家人,父亲是家人,label是控制项,form是控制项 2. 儿子是父亲,label是form 你认为哪个比较好? 你如果仔细看看,MS里的继承都是is的关系, 至少我trace过的都这样, 如果你有不认同MS的继承关系,麻烦告诉我,我很有兴趣。 许多人错用继承是因为like的关系, 一旦有这种关系在就必须要抽像然後建立一个基底类别来继承, 例如, 跑车跟卡车不是is的关系,是like, father跟son也不是is的关系,是like。 你跟我只是两点看法不同 1. 也许你会说没看到内容不确定他们的关系, 但我认为,命名本身就是重要的一点, 单纯看到father跟son我就当下认为是like所以我会抽像, 你会认为没什麽或不确定,就直接继承,其实很多人都这样。 2. 你认为在最小幅度内更动原PO程式码, 我认为要把正确的观念交给原PO,所以我连原PO的程式码也有保留起来, 单纯只是看法上的不同而已 说穿了,你如果要这样教也可以, 但我无法这样教,继承这种基础概念反而是最需要厘清的。 程式这东西本来就是经验与知识的累积, 你可以不认同,因为你有你的知识跟经验,这是正确的, 任何知识本来就要经过判断才吸收。
41F:→ ssccg:先不管son father这些名称,为什麽类别不应该继承类别? 05/19 17:22
42F:推 GoalBased:纯推讨论@@ 05/19 18:14
43F:推 hoyunxian:话说使用介面和继承基底类别到底差在哪? 05/19 21:36
44F:推 GoalBased:偶合性强弱的差别吧 楼上 05/19 21:39
应该说 介面 跟 抽像类别 吧!? 看的角度有很多,网路上也有许多人在讨论两种的差异。 我个人也有不同解释,根据学到经验也会有更多不同的解释, 搞不好三年後我又有不同解释,不过这东西怎麽解释都算对。 介面是对行为的抽象,可抽拔的,弱耦合 抽象类别是对类别的抽象,不可抽拔的,强耦合。 (也有人认为,C#把多重继承取消,所以介面是顶替多重继承。) 以介面来举例的话,我会推4.5有的Iobserver跟Iobserverble, 任何class我想做观察者模式,就加上这两个介面, 不想要的时候我就拔掉。 抽象类别的话,可以看Button跟ButtonBase。 不管名称或是成员,摆明就是强耦合。 通常是用在对一整个类别群的抽象或某一个特定的类别上。
45F:推 drizzt123:类别继承类别没有问题吧,随便建一个winform方案,都是 05/20 00:41
46F:→ drizzt123:form1:form 在"深入浅出C#"中举例,蜜蜂有工蜂(CLASS), 05/20 00:44
47F:→ drizzt123:"介面与防止重覆程式码无关,而是跟让一个类别可以应用 05/20 00:50
48F:→ drizzt123:在多种情况有关。 05/20 00:54
先推深入浅出这本书,入门的好书。 form1:form 基本上是把form当基底类别使用了, 相信很多人是 new form1(),而不是 new form(),这差很多。 基底类别通常都不会产生实体(new),是单纯拿来继承用的, (基底类别可以是介面、抽向类别、类别) 如同我上面的family如果用类别不用抽象类别可不可以, 当然可以,但我不会拿他来产生实体(new family())。 类别不能继承类别,有几个情况下才能打破, 1. 继承至「同一个」基底类别,基底类别不会拿来new 2. is 的关系 3. 自己依情况打破 (其实应该讲「类别不该继承至衍生类别」,这比较符合我要说的原意) (不过基底类别能成为抽象的话我都会用抽像类别或介面) 如果继承关系画成树状图的话, 通常root是基底类别,只拿来继承, leaf是衍生类别,拿来作实体,不会拿来继承。 而且说实在的,原则有很多,不管什麽SOLID或是其他的, 该怎麽根据实际情况而取舍本来就是工程师的工作之一, 世上不可能有100%遵从所有原则的程式,只有经过取舍後的程式, 但原PO的例子是要抽像没错,且不要类别继承类别。 实作上我也会用到类别继承类别,但我继承的是同一个基底类别, 我不会拿衍生类别继承衍生类别。 假设我有3个固定的view,那这3个我会继承至Form。 以下两种继承可以看看差别 1. From1:Form Form2:Form Form3:Form 2. Form1:From Form2:From1(类别继承衍生类别) Form3:Form2(类别继承衍生类别) 很明显第二种继承就是坏继承,但很不幸的这种继承很常见, 尤其程式经过多次不同人的维护後,这种情况很容易发生。 (如果去掉form这种常见的东西,自定义的类别很常出现衍生类别继承衍生类别) 类别要继承类别,最好继承至同一个基底类别, 如果以原PO例子看看哪个比较好。 1. Father:Family Son:Family 2. Son:Father 说实在的, 讨论这也只是自爽用的,老板才不会管你用啥方式, 只要会跑就好,不会挂掉就好, 我想这是每一个工程师的心酸所在。 在怎麽嘴炮,也不如手上白花花的银子还实在。 ※ 编辑: StupidGaGa (60.249.117.38), 05/20/2014 11:24:32
49F:推 GoalBased:这叫做工程师的浪漫 05/20 12:59
50F:→ StupidGaGa:巨大机器人(变形金刚)与巨大怪兽(哥吉拉)是男人的浪漫 05/20 13:32
51F:→ ssccg:IntegerTextBox : FormattedTextBox : TextBox : Control 05/21 09:12
52F:→ ssccg:例你Form那个例子,你觉得这是坏继承? 05/21 09:13
53F:→ ssccg:要继承就是要省掉同样的部分,为什麽还要特地从基底继承? 05/21 09:13
54F:→ ssccg:你说有几个情况才能打破的 2 is的关系 05/21 09:13
55F:→ ssccg:继承本来大多数就是因为is的关系才继承,怎麽变例外了? 05/21 09:14
56F:→ KanoLoa:观念很好很棒,但是拿原PO的例子根本矫枉过正... 05/23 00:13







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Gossiping站内搜寻

TOP