就你这段话就可以看出...没必要再和你讨论了...
另外我从来没有表示过对别人的书有不屑之意...只是所谓读书不能读死书的意思...显然阁下的理解能力与众不同...
长篇大论未必有力...说话要说到点子上...
到底是多重继承还是单链继承更符合现实世界这本来就是一个没有意义的问题,就像我们不是因为面向对象更符合我们真实的世界才选择面向对象的一样。说面向对象是从现实世界中抽象而成的理论我想在任何一个资深的OO程序员来说都知道这只不过是把OO变得玄之又玄的新手入门教材而已。
OO能够抽象我们的程序,提高代码复用率,降低耦合度,使得程序可伸缩性更佳,这些是我们选择OO的原因,而不是因为我们把我们的家抽象成了一个Object然后从日常生活中脑子一拍想出了程序。
引用 37 楼 vrhero 的回复: 另外从OO的角度看...儿子仅仅是男性属性决定的一个属性...与父亲、教师、老公、情人等等有本质的区别...------
在面向对象的程序设计中,由于C++的引入而显得尤为突出的一个问题是:所有类最终是否都应从单独一个基础类继承。在C#中(与其他几乎所有OOP语言一样),对这个问题的答案都是肯定的,而且这个终级基础类的名字很简单,就是一个“Object”。这种“单根结构”具有许多方面的优点。
单根结构中的所有对象都有一个通用接口,所以它们最终都属于相同的类型。另一种方案(就象C++那样)是我们不能保证所有东西都属于相同的基本类型。从向后兼容的角度看,这一方案可与C模型更好地配合,而且可以认为它的限制更少一些。但假期我们想进行纯粹的面向对象编程,那么必须构建自己的结构,以期获得与内建到其他OOP语言里的同样的便利。需添加我们要用到的各种新类库,还要使用另一些不兼容的接口。理所当然地,这也需要付出额外的精力使新接口与自己的设计方案配合(可能还需要多重继承)。为得到C++额外的“灵活性”,付出这样的代价值得吗?当然,如果真的需要——如果早已是C专家,如果对C有难舍的情结——那么就真的很值得。但假如你是一名新手,首次接触这类设计,象C#那样的替换方案也许会更省事一些。
单根结构中的所有对象(比如所有C#对象)都可以保证拥有一些特定的功能。在自己的系统中,我们知道对每个对象都能进行一些基本操作。一个单根结构,加上所有对象都在内存堆中创建,可以极大简化参数的传递(这在C++里是一个复杂的概念)。
利用单根结构,我们可以更方便地实现一个垃圾收集器。与此有关的必要支持可安装于基础类中,而垃圾收集器可将适当的消息发给系统内的任何对象。如果没有这种单根结构,而且系统通过一个句柄来操纵对象,那么实现垃圾收集器的途径会有很大的不同,而且会面临许多障碍。
由于运行期的类型信息肯定存在于所有对象中,所以永远不会遇到判断不出一个对象的类型的情况。这对系统级的操作来说显得特别重要,比如违例控制;而且也能在程序设计时获得更大的灵活性。
但大家也可能产生疑问,既然你把好处说得这么天花乱坠,为什么C++没有采用单根结构呢?事实上,这是早期在效率与控制上权衡的一种结果。单根结构会带来程序设计上的一些限制。而且更重要的是,它加大了新程序与原有C代码兼容的难度。尽管这些限制仅在特定的场合会真的造成问题,但为了获得最大的灵活程度,C++最终决定放弃采用单根结构这一做法。而C#不存在上述的问题,它是全新设计的一种语言,不必与现有的语言保持所谓的“向后兼容”。所以很自然地,与其他大多数面向对象的程序设计语言一样,单根结构在C#的设计方案中很快就落实下来。
------
to Ivony:
只是他一个人在为那句话争论而已...现实世界的复杂性不是现有的计算机技术可以描述的...所以我们才尽量的简单化来抽象...
to sjjf:
都说不想再讨论了...所以只回答你的疑问...
第一点:在我的问题域中,所谓的角色依靠职能而存在,
一个叫人的物体所拥有的各种职能在我们需要用到这个概念的时候,
在他出现的场合就已经拥有这些职能了,
而不是一会儿加一个职能,转化成某个状态后再动态加一个职能,
在软件里,很难做到这样一点。
-------------
专有名词扯再多看不破本质都是纸上谈兵...如果你不能理解儿子是一个属性而父亲、教师、老公、情人等应该是接口我并不奇怪...
疑问1: 是我引用错了,还是书本错了,如果错了,错在哪儿?
疑问2: 你觉得那些地方那些地方不能相信?为什么?如果采用你的所谓的无书?
那如何证明我的决定是对的?
疑问3: "另外书也是人写出来的..."你是想告诉我书不尽正确,
还是想告诉我那些书没啥大不了的?还是想告诉我其他的别的什么?
-------------
基本上我不知道你的疑问都是怎么总结出来的...我从头至尾没有说你引用错了也没有说书本错了更没有说谁的不能相信...只是想告诉你知识不是简单堆积消化理解了才是自己的...前人的经验不但是总结更是破除了更前人的经验得来的...如果你不能理解尽信书不如无书这句话那更没什么可说的了...
------
专有名词扯再多看不破本质都是纸上谈兵...如果你不能理解儿子是一个属性而父亲、教师、老公、情人等应该是接口我并不奇怪...
========================================================
有点无语,也许你要真正做到设计师才能理解我要表达的意思。
至少要真正的用过一次oo思想来分析和做解决方案后了你才能理解。
我举的面向对象分析与设计一书中的桌子和组成部分的关系的例子就
是想告诉你问题域的重要性,可惜你没有去翻过。
如果你不能对问题域,角色这样的名字敏感,那也说明你还不是设计师,
至少,还达不到设计师的层面。
算了,多说无益,你还以为我在侮辱你的iq。
------
单一继承更符合真实的世界。面向对象本身起源于实际生活。
如果LS两位只是为了这么一句话而争论的话,就显得太过于无聊了。
到底是多重继承还是单链继承更符合现实世界这本来就是一个没有意义的问题,就像我们不是因为面向对象更符合我们真实的世界才选择面向对象的一样。说面向对象是从现实世界中抽象而成的理论我想在任何一个资深的OO程序员来说都知道这只不过是把OO变得玄之又玄的新手入门教材而已。
OO能够抽象我们的程序,提高代码复用率,降低耦合度,使得程序可伸缩性更佳,这些是我们选择OO的原因,而不是因为我们把我们的家抽象成了一个Object然后从日常生活中脑子一拍想出了程序。
==============================================================
to Ivony,
我并不认为单一的继承更符合真实的世界,
比如现在有的双性生物都是双继承的,甚至是多继承的,例如花授粉。
菱形继承在古代甚至现代也是有,例如近亲结婚,当然并不是严格的封闭菱形,
但可以找到菱形的。
单一的继承也可以解决问题,不过并非优雅的设计。
就像lambda算子中的多参数总可以curry化成单参数一样,
两者是等价的,但是琐碎程度不一样。
我在前面也提过,单继承+接口方式对上也能实现多继承功能,
但是就像在饥饿的沙漠里面逮住了一只蜥蜴一样,虽非美味,为了
填饱肚子求生存,也只能强咽下去。
我用过java,也用过cpp,说实话,比拼coding,我也不一定输给某些人,
这点我还是有自信的,比拼design,我也不惧大多数,因为我困惑过,思考过,
并找到理论依据。
我有两年半的青春是花在java上面的,说实话,尽管java中接口满天飞,
我对这种方式没有什么好感,(没用过c#,不知道它和java的方式有什么不一样)
缺点我已经说了,设计复用性相对较差(当然是拿优良的java设计和优良的cpp设计来说的)
代替的解决方案缺点也很多,惟一可以带点说服力的是垃圾回收。
但是一个良好的设计是可以稍微花费一点开销就能够取得内存自动管理,
在开发效率和运行效率之间取得了最高的比率。
这方面具体的例子可以参考geant4,一个开源的空间物理计算引擎,
里面用到了很多cpp的oo设计技巧,很优雅,没事干的可以下来玩玩。
so,我说单继承+接口更适合愚蠢的人用,这话并不过份。
语言,思想,不过是我们描述世界的一种工具而已,
不能简单地对面向对象是否真的合适描述我们的现实世界这样的问题下一个对或者错的结论。
刀剑有刀剑的用处,枪炮有枪炮的妙用,但任何工具都有合适使用的范围。
这个使用范围就是我们的软件设计里面的问题域。
关于面向对象,本公子今天比较无聊,顺便忽悠一番。
在很久以前,有个家伙叫图灵,为了证明可计算问题是真的可以求解的,
造出了一个叫图灵机的玩意儿(计算模型),同时还催生了叫算法的玩意儿,
这是计算理论里面的可计算性和计算复杂度的内容。
(其实,同时代的还有邱奇的lambda算子,和一个忘了名字的人提出的递归函数,)
这些内容为形式演算奠定了理论基础,使自动计算成为可能。
后来,有个叫冯诺依曼的家伙,雇佣了300名女工为原子弹的扩散影响范围计算了几个月后,
非常苦恼,偶遇了一个军方人士后,在图灵机的模型上加上了可存储单元(内存)
捣鼓了一个可以自动计算的机器。后来慢慢的演化成现在计算机。
在最初的岁月里面,人们的工作重点是把自然语言里面表达的思想影射到机器可以识别的语言里面,以便可以驱使机器进行自动化的计算。繁琐的机器语言让人头晕脑胀,于是有人为了便于记忆
使用了些助记符号,于是产生了一个叫汇编代替品。
汇编语言提供的描述点是寄存器,移动,寻址,压栈,入栈,算数运算,位运算,调用
等描述点,提供的机制几乎是靠硬件实现的,如保护模式,段页式等。
so,适合汇编的问题域是关于机器操纵的。
在这种细粒度的语言描述下,要来描述现实中的模型,差距太大,
组合爆炸使其就像用一堆细胞来描述一个人体一样恐怖。
so,基本上汇编只用来描述最关键性的东西,
从现实中提出去需要的计算,转换成机器操作是机器语言程序员工作。
在经过大量的使用后,人们发现在描述任务的步骤地时候,出现了一些稳定的特征,
例如有条件跳转的几种固定模式,循环的几种用法,局部变量,代码块(函数),
这些特征经过适当的封装,形成了新的描述点,同时涌现出了顺序,分支,循环,递归等流程机制,
于是便出现了过程化语言,它将任务的描述从机器层面解脱出来,扩大到面向过程式任务步骤层面,这时候类似描述一个人体就用躯干四肢和头来表达,
描述的粒度开始变大,直接影响了可描述任务的复杂度和规模。于是导致了c璀璨了近40年,
并在系统编程领域称霸,描述任务,它再合适不过了。
从现实模型中提取出需要的任务描述,是过程化语言程序员工作。
当问题域涉及描述一个系统的时候,
过程式的语言就显得力不从心,就像描述一个公司系统内部的聚餐的时候,
用一堆堆躯干四肢和头和嘴如何移动来表现一样,虽然在有限的范围内,它也可能
描述的清楚,当容易转移人们的焦点,人们更关注的是系统的组,系统的状态,
系统的交互行为,系统的协作程度,而不是某一部分是如何移动的。
这迫使新的语言要提供一个更大的描述点,能够更贴近我们的生活模型,
我们的生活抽象出来的模型,是由一些系列的概念,以及概念的交互构成的。
因此oo应运而生,虽然很多人理解这个语言中类的概念是数据+函数,
但是忽略了有机构成几个字,不知道其中某些东西已经发生了质的变化,
就像木偶也是有四肢+躯干+头构成,但是却无法拥有生命,
oo,正是那个像木偶吹了口仙气的上帝,以封装,继承,多态等机制赋予类一个活的概念。
恩,先到此为止,有事外出,下次再忽悠。
------
额..这个和面象对象编程有关吧。
比如说人。。只会有一个父亲一样。。 但是他可能会有多个人的行为习惯。。~
抽象到程序里来就是单一继承和多接口实现。。
------
up,精彩,jj兄。
------
C#面向的使用者和应用层次不同
无论那一种语言,都必须考虑到使用的环境和语境
------
小林,说起这个比yy还厉害
------
引用 10 楼 knight0450 的回复: 总结来讲就是更加接近JAVA,当初MS推出C#对手就是JAVA。java和C#都是单继承多接口。多继承容易出错是程序员实践中总结来的------
引用 10 楼 knight0450 的回复: 总结来讲就是更加接近JAVA,当初MS推出C#对手就是JAVA。java和C#都是单继承多接口。多继承容易出错是程序员实践中总结来的------
单继承更容易理解,要不然哪里来这么多人看csdn
------
上面的争论跑远了,多接口确实比多继承清楚,LZ自己写个简单的控制台程序看看就明白了
至于哪种好,更符合实际-----sjjf兄写的太长了,有没有中心句什么的放在段首啊,我看的头晕,就看了一贴,相当有文采,能忽悠。
(其实各人对世界的认知都是不同的,有毛线争的,我自认还没上升到那个理论高度,能很好的实现我就OK了~,也许再过个5年我能想想这问题)
------
see EC++ 43
------
sjjf兄写的太长了,有没有中心句什么的放在段首啊,我看的头晕,就看了一贴,相当有文采,能忽悠
-------------------------------------------
本来就在乱弹,何须中心?
继续昨天的忽悠。
在讨论oo之前,让我们回头看看我们人类的一些基本认知。
以下观点纯属个人的扯淡,如有雷同,纯属偶合 :)
几百万年之前,我们的祖先茹毛饮血,所见所闻也基本是口舌相传,
知识的积累基本是新增和流失相对比例不会变化太大,
也许新增比流失总是要多一点点,
我认为在一段时期内,知识的新增和流失比例不会变化太多,
因为人脑的记忆和检索是有限制的。
这种状况直到其中某一个聪明的祖先学会了外物作为载体进行知识存储。
例如木绳记事。这将使知识得以脱离口舌进行传承。
从此在一个部落内,如果知识存储规则明确后,知识的流失量几乎成0。
虽然知识已存储,但是受限于部落规则的制约,成为信息孤岛。
知识孤岛之间不能流通和融合。可以想象一下当时的格局,
在苍茫的大地上,遍布了大大小小的原始部落,这些部落之间都有自己的知识储备,
就像星星的火种,一点一点的顽强的闪着,随时都可能会随着部落的消亡而熄灭。
随着进化,这些部落慢慢的学会了沟通,慢慢的在局部地区,语言开始有了交集
或者开始了统一。为部落之间的规则的流通提供了可能。
直到区域的部落之间统一的文字,规则的流通才畅通无阻,解读了规则,
也就能使知识融入在一起,
从此,知识在区域之间开始了雪球效应,那些星星之火终成燎原之势。
发展到今天,已走向全球的文字和语言的统一,虽然不是形式上的统一,
但是至少语言之间的同构关系已经建设起来,虽然没有全能的地球语翻译机,
但各种语言之间大体已经能够互相翻译了。
人类在走过几千年的发展路程中,所见,所闻,所思,所说成淀下来的知识量日益庞大,
不知道从何时起,知识量已经超过了人脑的处理极限,一个人要想读完自己的国家的博物馆的
所有书,估计也要穷其半生或者一生。
人类的大脑在庞大的知识库面前开始感觉掌控无力,
这是便开始研究大知识量下的掌控方法,这些方法无非也是在知识的量和深度方面做文章。
在深度背后探索知识的规律,在量方面采用更有效的知识管理手段,
例如牛顿三大定律使得宏观世界的运动得到统一,让人们抛弃了纷乱复杂的运动现象,只需记住简单的但抽象的物理定律,这是知识深度的拓展,
在知识管理的工具方面计算机技术的发展,使得人类在信息量的掌控方面得到了极大的扩展。
在知识管理的方法方面也发展出了分类理论,文献检索技术等
其中分类理论是我们所要关注的。
分类理论从现实中提取出具体事物的抽象描述(也就是俗称的概念),以图的方式(主要是树)
展现了概念与概念之间的关系,为我们描绘了世界认知的静态框架图。
oo借鉴了这种描述世界的方式,这些描述方式都是有数学基础支撑的,
例如类的划分标准是集合论里面的等价关系,泛化是一种偏序关系等等等。
有人发表了一篇论文叫 面向对象方法学理论基础 这本书讲的比我要好多了,就不累述了。
uml与模式应用一书中忽悠我们在提炼类的概念的时候,其中有一种方法是借鉴事实。
这也是有道理的。
提出了类的概念出来后,在构建一个类的体系的时候,有三种策略:自顶向下的演绎法
自下向上的归纳法,还有两者兼有之的混合法,
实际上如果和机器学习比较一下,你会发现这两者采用的策略竟是如此雷同。
我们在用oo分析与设计来描述我们的需求时,
不过是在大脑中虚拟了一种机器从另一个视角来重新认识我们的世界。
------
ec++ 43中 scott meyers 关于多继承的论述,我并不尽赞同。
cpp多重继承很强大,但是不至于强大到为所欲为。
比如传说的人马,假设是从人和马两个继承下来的,
那么人马到底是用人的方法跑还是用马的方法跑呢?
我们人脑可以根据人马的形象,下半身是马,那肯定是用马的方法跑,
如果我以前都没有见过人马的形象,那我也判断不了到底人马是用人的方法跑还是
马的方法跑,人都无法判断,何况只拥有那点有限的规则的编译器呢?
没被足够的信息作判断,二义性是无法自动消除的。
所以我觉得scott meyers举的例子本身就不恰当。
我不觉得我下面的代替方案有啥不妥。
class Lottery {
public:
virtual int draw(){printf("\nlottery::draw");};
};
class GraphicalObject {
public:
virtual int draw(){printf("\n GraphicalObject::draw");};
};
class LotterySimulation: public Lottery,
public GraphicalObject {
public:
virtual int draw()
{
printf("\n assume draw");
return GraphicalObject::draw();
};
};
把 lottery ==>人,
GraphicalObject==>马,
LotterySimulation==>人马
draw==>跑 就是我想要实现的东西了。
在冲突的地方我显式地指明,
如果除了跑这个动作外,如果我想用的其他的东西都没有逻辑上的冲突,
那用隐式继承下来的东西,我想还是利还是大于弊,
如果大部分的东西都存在冲突,那么就需要考虑设计的合理性了,
也许那并不适合用多重继承来复用。
to be continue......
------
有些人说:“有些人之所以被称为高手,是因为他们在思想上走的更远。”
那么---水晶剑锋.林公子---足已被称为高手了,就算不是高手,至少也是一个“思想者”。
因为他考虑问题比一般人站的都高,看问题比一般人更客观,对事物认识的比一般人更深。
------
引用 83 楼 sjjf 的回复: ec++ 43中 scott meyers 关于多继承的论述,我并不尽赞同。 cpp多重继承很强大,但是不至于强大到为所欲为。 比如传说的人马,假设是从人和马两个继承下来的, 那么人马到底是用人的方法跑还是用马的方法跑呢? 我们人脑可以根据人马的形象,下半身是马,那肯定是用马的方法跑, 如果我以前都没有见过人马的形象,那我也判断不了到底人马是用人的方法跑还是 马的方法跑,人都无法判断,何况只拥有那点有限的规则的编… ------ ls的,我没有看过ec++ 我认为熟悉cpp语言,靠 cpp标准语言特别版 , cpp设计与演化, cpp gotchas,就够了, 昨晚我特地花了半个多小时的时间认真地读了 ec++ 43,通读一遍之后,我大致理解了作者意思, 但是实在太累了,我就只针对第一部分发表了些看法, 请你再仔细看看,作者提出来的解决方法是否和我的一样。 晚上有空再忽悠。 ------ sjjf很能忽悠,崇拜下orz ------ 关于多重继承的二义性,是在编译期就可以检查出来的,也有解决方案,不能算是一个缺陷, 只不过是复杂一点(主要集中在编译器的实现上,而不是设计和使用上), 不过现实就是这么复杂的,他只是忠实的描述了现实而已。 ====================== c++ 编译器可以这么实现,因为c++是源代码级面向对象,C#确不行,.net 下所有对象都是继承与object,多重继承的避免不了菱形继承,那样只有不让所有类继承于object,那么动态加载,垃圾回收所有基于运行时的面向对象部分怎么实现? ------ 我觉得也是对面向对象一种取舍。一些不常用的功能就能自然就取消掉了。 ------ 编码时优先考虑使用对象的合成/聚合,而不是继承,这样有利于类的封装, 当需要多重继承的时候不妨考虑用用合成聚合 ------ 我是这样理解的,C#并不是单一继承 每个类都默认继承了object 这个就像是蚁后,然后能够初始的制造蚂蚁,然后有雄蚁(基类) 两个结合又能产生新的蚂蚁(子类) 继承接口就像是学会了什么技能,新的蚂蚁继承了搬东西接口,它就变成工蚁,当然或许还要继承吃饭接口等等。 同样继承了打架接口的,就变成了兵蚁。 这样在逻辑上就显现比较符合思维习惯 多个继承的话,条理上就比较混乱,就像一只蚂蚁是由工蚁雄蚁加兵蚁雄蚁加蚁后产生。 ……这要怎么理解,而且为了制造这样的东西,我们还不得不去做 工蚁雄蚁 和 兵蚁雄蚁,可是雄蚁中却又不存在这样的品种 所以我个人觉得这样的继承是为了更加符合逻辑,还有就是C#是结合了Java衍生的 ------ class AuxLottery: public Lottery { public: virtual int lotteryDraw() = 0; virtual int draw() { return lotteryDraw(); } }; class AuxGraphicalObject: public GraphicalObject { public: virtual int graphicalObjectDraw() = 0; virtual int draw() { return graphicalObjectDraw(); } }; class LotterySimulation: public AuxLottery, public AuxGraphicalObject { public: virtual int lotteryDraw(); virtual int graphicalObjectDraw(); ... }; scott meyers 举的AuxLottery的例子, 实际上为了隐性的引用draw 而采用夹层+wrap的方式下放出两个纯虚接口。 杀敌一个自伤两个,这个买卖不合算。 我认为这是一种更糟糕的设计方式,而不是代替方案。 其一,违反了复用的原则,其中,没有复用到些什么, 除了对上保持了draw接口的统一外,没有啥东西是复用的。 其二,作为类体系来讲, 为了一个隐形的引用,多增加了两个辅助接口,还下放到最底层的类实现。 比起将冲突的继承特征重新显式的指定,或者重新赋以新的涵义, 这种方式更差劲,没必要为了形式上的 多重继承 而束缚了自己的手脚。 so.这个不是合适的例子。 在类(概念)体系中,处于上位的类(概念),必定比下位类(概念)拥有更少的内涵, (下面请将类等同于概念,建议对这些名字感觉迟钝的朋友, 自己去弄懂客体,特征,概念,内涵,外延这些名词的意思, 当年我花了半个月的时间才理清这些名字的概念和关系, 这些逻辑学上的东西将更有助于作软件设计分析) 下位类是添加了更多内涵的类,这是我们之所以用继承的方式进行复用的原因, 对一个类的下位类,根据不同的问题域可有好几种不同的划分的标准, 这些标准将会导致会有不同的侧重区分特征的内涵加入子类。 多重继承就是期望在同一划分标准或者不同划分标准中, 能够拥有这些不同的上位类的概念特征, 可以假想一下,每一个概念代表一个特征的集合, 比如上位概念A 上位概念B 以及我们要的下位概念C 不管上位概念A和上位概念B处于何种位置, 相对于A和B来说,无非是A和B有交集,A和B没有交集 A和B有交集的情况就没有任何异议了,做为多重继承,不会存在任何的二义性。 对于A和B有交集,那么A和B肯定要处于一个同一颗树里(你大约知道菱形继承为什么会存在了吧), 否则,要么这个交集将不是我们需要关注的,要么,我们的抽象出了问题。 如果交集中的特征中,型和值都一致,那么,这是最好的情况,也不会产生任何的二义性问题 因为不管是A的特征还是B的特征,都是同一个玩意儿, 如果型相同,值不一样,这就存在冲突了,那么我们需要考虑, 到底是采用A的值,还是采用B的值, 还是需要自己赋以新的值才能符合要求。 (如果型不同...天啊,那不可能...) 我们期望不做任何的改动就能将冲突部分解决,这是不现实的, 因为我们没有给编译器足够的信息,即使有这个信息也不知道如何传递给编译器, 只能手工来解决。当然,如果在问题域内,通过巧妙的设计,还是能避免二义性的问题的。 如果能达到这样一点,那将是最大程度的发挥多重继承的效用。 如果我们期待能够完全利用父类的所有特征, 而在用的过程又出现了scott meyers的所举的这个例子, 那就可能出现了两个问题: 第一,在该问题域内,某些层面的类划分标准并不清晰,导致冲突出现。 第二,层次抽象并不合理,我们可能对父类有太多的期望,加入了太多的内涵。 尽管scott meyers是大师,但是思考是属于我自己的,我的想法不一定对, 但目前我还没有能说服自己放弃自己的想法。不是狂妄,而是认真。 今天酒有点喝多了,姑且妄论之。 to be continue... ------ 1、一个类从另一个类派生除了纯虚函数,没有任何要求子类必须override它的virtual函数 ---------------------------------------------------------- 我想我并没有要求子类必须overide virtual函数, 我只是根据我的要求显式的指定 draw函数的实现。 之所以这么干,是因为我确定了如何手工解决二义性。 另:java里面的函数都类似virtual函数 不知道c#是不是这样。 2、如果两个父类同名函数有几十个怎么办 (//这里只是研究语言,不要讲设计不合理,因为有可能父类是不同的人设计的) ----------------------------------------------------------- 那种情况你就要考虑设计是否合理,如果是一个拙劣的抽象导致的丑陋的设计。 你需要重构而不是将就。 另外,为什么要将设计层的问题放到语言层面来解决呢? ------ 学习中!! ------ 菜鸟,初出江湖,看大侠们论战。招式一概不懂,一样看的有味。 我不知道儿子和父亲有何本质的区别,请告诉我本质性的区别。 --------- 这个世界上只要是男人就是儿子...但父亲必须要有实现...不是每个男人都一定是父亲也不是每个男人都一定会成为父亲...你不会连这点常识都不知道吧... -------- 仅从概念上理解,技术上的我不懂。本质区别,我理解的不深刻。“这个世界上只要是男人就是儿子”这句话的表达的意思应该指的是儿子的继承特性,儿子上面肯定有父亲的存在。在程序中,父亲是可以没有儿子的角色的,上帝也就是程序员创造了他,也就是说在程序中,父亲是可以有不继承这一特性的,所以,在程序中,通过继承这一特性,能区别出父亲儿子。但是在现实中的概念,父亲肯定也会是儿子,在整个时间段上是连续的,但是你找不到起点,你找不到初始的父亲,通过继承特性就区分不出父亲儿子的区别,父亲也是儿子。所以,想到这里有点混乱。 ------ 发完不能改啊。改句话。“也就是说在程序中,父亲是可以有不继承这一特性的”改为“也就是说在程序中,父亲是可以有无继承这一特性的” ------ to ifdone: OO重要的是真正理解对对象的抽象而不是套什么理论和概念... 男人一定是儿子是由“人”及其性别决定的...并且它是只读的简单数据...所以说它应该只是人的一个属性而已... 父亲则不同...一个人必须是男人而且还要与某个女人通过性行为后由这个女人经历怀孕、生产等过程之后才能够被其子代称为父亲...所以说它应该是一个需要实现的接口...如果将其作为一个可继承的根去理解那简直是滑稽... ------ 怕多继承被乱用所以舍弃了,多继承实际的类和接口那处理起来是两码事,接口是空的实现,而类则不是。 毕竟C#是更偏向设计架构层次的语言,多继承类虽然有好处,但是MS觉得这种习惯不好,就不要了. ------ 大道至简 ------ 这个问题很简单,为了实现低偶合嘛
桂ICP备07017180号