关于多态的问题

xuerueheng 2019-08-21 03:57:49
为什么要把子类对象付给父类变量而不是直接使用子类对象
...全文
1079 40 打赏 收藏 转发到动态 举报
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_45089420 2019-09-09
  • 打赏
  • 举报
回复
直接使用子类对象的话,如果要是用到父类的方法时还要进行单独调用父类,使用多态的话,就可以一步直接父类子类的方法都可以直接调用
thcSimu 2019-09-03
  • 打赏
  • 举报
回复
子类对象 子类实例 = new 子类对象;这样做是完全没问题的,跟普通的生成实例没有任何区别。父类引用指向子类对象是java多态的关键呀。一个父类肯定不是要求只有一个子类呀。
S-Hang 2019-09-01
  • 打赏
  • 举报
回复
这样你在封装函数时,就不需要知道具体是谁,只需要知道接收他的子类就好
tengjiaIT 2019-08-23
  • 打赏
  • 举报
回复
基类是类库的编写者先写好的。。
小灰狼 2019-08-23
  • 打赏
  • 举报
回复
引用 25 楼 xuerueheng 的回复:
所以您的意思是之所以要把子类对象赋给父类变量,是因为要把父类变量(或对象)传进一个方法内用它来进行计算,好方便它调用父类及子类内成员吗?但不是有个里式转换原则吗,他说父类不可以用子类成员,而子类可以用父类公开成员及子类内成员吗?
看来我还是没说明白这个道理 把子类对象赋值给父类类型的变量,就是说软件设计的人把注意力集中在父类类型上,而不去关心子类类型的无关的细节或者不同的实现 这么说有点抽象,举几个例子 1、“主食”有几个子类,面食、大米饭,它们还有子类,面条、包子、面包,大米饭、糯米饭,还有子子类,小笼包、担担面、东北大米饭…… 所以,对一个肚子饿的人来说,你给他“主食”即可,而你可以给他包子,也可以给大米饭…… 灵活性就体现出来了 你想想看,如果一个人很挑食,他只吃“张老板家包的小笼包”(就相当于你的方法只接受子类的类型,或者你定义的是很具体的子类类型的变量),你给他吃面条他是无法接受的。但实际上,按照实际业务逻辑,吃面条也是可以完成你的业务功能的。 2、如果你是一个老板,要招一个翻译(父类),而人事部给你招的人里,肯定是各种各样的子类:男性翻译、女性翻译,当然还会有更具体的子类,象生过一个孩子的女翻译、生过两个孩子的女翻译……没有结婚的女翻译……长得漂亮身材苗条又性感风情万种的女翻译…… 但是,你作为老板,只需要关注人事部给你招的是个“翻译”(父类型)就行了,只要他是这个类型,就能满足你的业务需要,而具体这个员工是什么子类型(有没有结过婚,有没有生过孩子,生了几个孩子,长得漂不漂亮、性不性感)都不是你需要关心的事。 所以,你的程序里: 翻译 obj = new 漂亮又性感的没结婚的女翻译(); 翻译结果 result = obj.做翻译工作(被翻译的内容); 或者 翻译 obj = new 又老又丑长得又猥亵的男性翻译(); 翻译结果 result = obj.做翻译工作(被翻译的内容); 强调一下,这种情况下你要关注的是父类的类型,是调用者如何使用的问题,而不是关注子类如何实现。你可以把父类(或者接口)当作一种定义好的规范,子类是对规范的一种实现。通过这种方式实现接口(或者规范)的使用与实现的分离,使用与实现的分离达到模块低耦合。 以上个例子来说,如果你原来的那个翻译(漂亮性感风情万种的女翻译)离职了,人事重新给你招了个翻译(子类:长得丑又猥亵但毕业于某985大学的专业对品的学霸男性翻译)。 如果你原来的代码是: 漂亮性感风情万种的女翻译 obj = new 漂亮性感风情万种的女翻译(); obj.做翻译工作(被翻译的内容 content); obj.m1(); obj.m2(); ...... 等人事部重新招人后,你上面的这段代码就要大改了。但实际上,你所需要的只是一个翻译而已,而你却把业务逻辑绑定到精确的类型上。 再举个例子,我国民用电力标准是平均电压220V、50Hz、正弦交流电(这是标准,你可以当它是接口,或者一个父类) 使用电源的有各种家用电器,电视机、洗衣机…… 提供这种电力的人各种发电厂(子类),有水力的、火力的、柴油机、太阳能发电…… 很明显,家用电器面向的是接口或者父类型,他根本不会关注电源从哪里来,不会有个电器说我只能使用水力发电厂提供的电源;而各种类型的电源,也不会限制电源的使用方(我发的电只提供给洗衣机用)
叫我 Teacher 周 2019-08-23
  • 打赏
  • 举报
回复
引用 楼主 xuerueheng 的回复:
为什么要把子类对象付给父类变量而不是直接使用子类对象
你爹的遗产是不是你继承,难道有说你的遗产你爹继承一说吗?
码原 2019-08-23
  • 打赏
  • 举报
回复
多态和动态绑定是计算机程序的一种重要思维方式,使得操作对象的程序不需要关注对象的实际类型,从而可以统一处理不同对象,但又能实现每个对象的特有行为。
xuerueheng 2019-08-23
  • 打赏
  • 举报
回复
引用 36 楼 小灰狼 的回复:
差不多是这个意思了吧
设计这些类时,有时要进行抽象,装逼的说法叫“泛化”,就是把共性的东西提出来,变成一个父类。
越向父类型走,类型越“泛”,越向子类型走,就越“精确”

明白了,谢大佬
xuerueheng 2019-08-23
  • 打赏
  • 举报
回复
引用 31 楼 wanghui0380 的回复:
你要知道对象化编程到底是怎么来。
在对象化出来以前最流行的是结构化编程,过程式编程(实际当年也有函数式,声明式不过不流行)

而那种编程最后的结果就是,每次变化就得重新写。
后来人们发现,我为啥要重新写,明明逻辑一样,个别细节不同,都重新写,写死了哦,写到公司垮了都写不完

所以产生了范型编程和对象编程两类

这两种都是对类型编程,只要类型一样就可以扩展,但外面调用一样

so
现在想想你的问题

就像你说的。

如果你一点要写成
白马.跑
黑马.吃草

请问以后 红马,棕马怎么办

所以我们只对马编程,马会跑,马会吃草。这样就行了。就算你以后新加一个七色马,我的代码也不用动,我们不会加班,不会996

如果都是像你说的,代码里全是白马,红马这样每个都不转,我是说“996 ICU”都不够,应该是“12127骨灰盒”才成

大佬别急,我懂了,我结贴了
小灰狼 2019-08-23
  • 打赏
  • 举报
回复
引用 35 楼 xuerueheng 的回复:
也就说我如果要做一个事情,我可以把这个这个事情内要处理的对象定义成一个父类,然后在把具体要处理的子类对象付给这个父类的变量,这样的好处是我以后要处理其他具体的子类对象时,就不需要改具体的代码了,只用把父类里赋得子类对象换一下就行。 大佬,我这样理解有没有问题呢?
差不多是这个意思了吧 设计这些类时,有时要进行抽象,装逼的说法叫“泛化”,就是把共性的东西提出来,变成一个父类。 越向父类型走,类型越“泛”,越向子类型走,就越“精确”
xuerueheng 2019-08-23
  • 打赏
  • 举报
回复
引用 34 楼 小灰狼的回复:
[quote=引用 25 楼 xuerueheng 的回复:] 所以您的意思是之所以要把子类对象赋给父类变量,是因为要把父类变量(或对象)传进一个方法内用它来进行计算,好方便它调用父类及子类内成员吗?但不是有个里式转换原则吗,他说父类不可以用子类成员,而子类可以用父类公开成员及子类内成员吗?
看来我还是没说明白这个道理 把子类对象赋值给父类类型的变量,就是说软件设计的人把注意力集中在父类类型上,而不去关心子类类型的无关的细节或者不同的实现 这么说有点抽象,举几个例子 1、“主食”有几个子类,面食、大米饭,它们还有子类,面条、包子、面包,大米饭、糯米饭,还有子子类,小笼包、担担面、东北大米饭…… 所以,对一个肚子饿的人来说,你给他“主食”即可,而你可以给他包子,也可以给大米饭…… 灵活性就体现出来了 你想想看,如果一个人很挑食,他只吃“张老板家包的小笼包”(就相当于你的方法只接受子类的类型,或者你定义的是很具体的子类类型的变量),你给他吃面条他是无法接受的。但实际上,按照实际业务逻辑,吃面条也是可以完成你的业务功能的。 2、如果你是一个老板,要招一个翻译(父类),而人事部给你招的人里,肯定是各种各样的子类:男性翻译、女性翻译,当然还会有更具体的子类,象生过一个孩子的女翻译、生过两个孩子的女翻译……没有结婚的女翻译……长得漂亮身材苗条又性感风情万种的女翻译…… 但是,你作为老板,只需要关注人事部给你招的是个“翻译”(父类型)就行了,只要他是这个类型,就能满足你的业务需要,而具体这个员工是什么子类型(有没有结过婚,有没有生过孩子,生了几个孩子,长得漂不漂亮、性不性感)都不是你需要关心的事。 所以,你的程序里: 翻译 obj = new 漂亮又性感的没结婚的女翻译(); 翻译结果 result = obj.做翻译工作(被翻译的内容); 或者 翻译 obj = new 又老又丑长得又猥亵的男性翻译(); 翻译结果 result = obj.做翻译工作(被翻译的内容); 强调一下,这种情况下你要关注的是父类的类型,是调用者如何使用的问题,而不是关注子类如何实现。你可以把父类(或者接口)当作一种定义好的规范,子类是对规范的一种实现。通过这种方式实现接口(或者规范)的使用与实现的分离,使用与实现的分离达到模块低耦合。 以上个例子来说,如果你原来的那个翻译(漂亮性感风情万种的女翻译)离职了,人事重新给你招了个翻译(子类:长得丑又猥亵但毕业于某985大学的专业对品的学霸男性翻译)。 如果你原来的代码是: 漂亮性感风情万种的女翻译 obj = new 漂亮性感风情万种的女翻译(); obj.做翻译工作(被翻译的内容 content); obj.m1(); obj.m2(); ...... 等人事部重新招人后,你上面的这段代码就要大改了。但实际上,你所需要的只是一个翻译而已,而你却把业务逻辑绑定到精确的类型上。 再举个例子,我国民用电力标准是平均电压220V、50Hz、正弦交流电(这是标准,你可以当它是接口,或者一个父类) 使用电源的有各种家用电器,电视机、洗衣机…… 提供这种电力的人各种发电厂(子类),有水力的、火力的、柴油机、太阳能发电…… 很明显,家用电器面向的是接口或者父类型,他根本不会关注电源从哪里来,不会有个电器说我只能使用水力发电厂提供的电源;而各种类型的电源,也不会限制电源的使用方(我发的电只提供给洗衣机用) [/quote] 也就说我如果要做一个事情,我可以把这个这个事情内要处理的对象定义成一个父类,然后在把具体要处理的子类对象付给这个父类的变量,这样的好处是我以后要处理其他具体的子类对象时,就不需要改具体的代码了,只用把父类里赋得子类对象换一下就行。 大佬,我这样理解有没有问题呢?
wanghui0380 2019-08-22
  • 打赏
  • 举报
回复
你要知道对象化编程到底是怎么来。
在对象化出来以前最流行的是结构化编程,过程式编程(实际当年也有函数式,声明式不过不流行)

而那种编程最后的结果就是,每次变化就得重新写。
后来人们发现,我为啥要重新写,明明逻辑一样,个别细节不同,都重新写,写死了哦,写到公司垮了都写不完

所以产生了范型编程和对象编程两类

这两种都是对类型编程,只要类型一样就可以扩展,但外面调用一样

so
现在想想你的问题

就像你说的。

如果你一点要写成
白马.跑
黑马.吃草

请问以后 红马,棕马怎么办

所以我们只对马编程,马会跑,马会吃草。这样就行了。就算你以后新加一个七色马,我的代码也不用动,我们不会加班,不会996

如果都是像你说的,代码里全是白马,红马这样每个都不转,我是说“996 ICU”都不够,应该是“12127骨灰盒”才成
wanghui0380 2019-08-22
  • 打赏
  • 举报
回复
你一定要纠结一下
我明明new的是白马,他不是马,你们干嘛都说白马是马,明明不是,他就是白马

我new白马,一定就是白马,肯定不是别的马
wanghui0380 2019-08-22
  • 打赏
  • 举报
回复
对,清空你的脑袋,把那个A=new B扔一边去,什么A,什么B,什么父类,什么子类通通见鬼,乱人心智。

你就用中文里理理。

美食 撒尿牛丸,黯然销魂饭算不算美食
要举办美食节,凭啥不让他们上

马 马=new 白马()
对不对
难道你想学“白马非马”
fengmind 2019-08-22
  • 打赏
  • 举报
回复
比如小汽车CAR这个类,他有不同的子类,两个大的方向,自动档AUTO和手动档HAND。CAR可以挂档,不管你手动还是自动,反正只要给我挂档就行!
wanghui0380 2019-08-22
  • 打赏
  • 举报
回复
厨子的这个类型是做菜

我朋友来了,我想请个好厨子做点好菜

你干嘛一定要纠结非得是

米其林三星大厨 厨子=new 米其林三星大厨

为啥就不能是
好厨子 厨子=像食神里一样的,某个苍蝇馆子,但有神级厨艺的厨子
wanghui0380 2019-08-22
  • 打赏
  • 举报
回复
我以为结束了,居然还是没有理解。

已经说过了,A=new B
那是书上让你理解的例子,不是我们故意要如此

而是针对类型编程,类型是已知的。实例是未知的。

就像前面说的,我开店针对有钱人,这类人已知。至于来的是谁不重要

同样医生针对病人,病人是谁不重要。话说30年前还没有社保这么一说,难道那时候的医生就不看病,不开药么,自古就有医生,自古医生就是一个类型,自古医生就要看病开药,上古巫医这个实例也一样,只是他开的药也许是求神仙
exception92 2019-08-22
  • 打赏
  • 举报
回复
个人理解多态就是用子类来实现父类行为状态的多种表示.楼上例子很好
xuerueheng 2019-08-22
  • 打赏
  • 举报
回复
引用 19 楼 小灰狼 的回复:
为什么把子类对象赋值给父类变量?

因为你用父类变量,可以只关注父类的一些特征,不必被子类类型所拘束和限制,使用父类类型有更大的灵活性

比如你有一个类叫物流公司,它有一个方法是运输,里面的参数是运输工具:
class 物流公司 {
运输(运输工具 obj){
......
}
}


而运输工具有很多种:
船、火车、货车、三轮车
再细分下去,货车有大型货车、中型货车、小型货车;火车有绿皮车、高铁……车轮车有人力车轮车、电动三轮车、汽油三轮车……

如果你的 transport 方法参数定义的是父类类型:运输工具,那么调用者可以用它的任意一个子类类型作为参数传入进去
而如果你的方法里定义的是子类类型:运输(电动三轮车),就意味首你开的这家公司只能用电动三轮车运货了……

所以我说,定义父类进行抽象,是让系统设计的人只关注它被抽象出来的特性,而忽略实际实现中被无关的细节。


实现一点的例子
无论是是哪种关系型数据库,想访问数据库都离不开对数据库的连接和关闭。所以,有一个父类:IConnection(好象是叫这个名,虽然是接口,但你可以当它是父类),它定义了 Open和Close方法。其它的子类象 SQLConnection, OracleConnection, MySQLConnection…… 都是它的子类。
如果我们要开发一个统一管理连接的连接管理器,你的管理器里就应该使用 IConnection ,而不是子类型,否则你的连接管理器就只能管理特定的一种数据库。

所以您的意思是之所以要把子类对象赋给父类变量,是因为要把父类变量(或对象)传进一个方法内用它来进行计算,好方便它调用父类及子类内成员吗?但不是有个里式转换原则吗,他说父类不可以用子类成员,而子类可以用父类公开成员及子类内成员吗?
threenewbee 2019-08-22
  • 打赏
  • 举报
回复
引用 13 楼 caozhy 的回复:
简单来说,基类是类库的编写者先写好的。编写的时候,派生类不存在。 派生类是菜鸟程序员后写的,写好传给类库调用。
比如说asp.net里面 你的 class _default : Page {} winforms里的 class Form1 : Form 对于asp.net winforms的类库编写者来说,他不是不想直接调用,但是没办法调用啊。 他的类库先写好,那时候只有 Page Form 你拿到手,才编写出来 _default 或者 Form1
加载更多回复(20)

110,526

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧