📣 VIP通行证夏日特惠 限时立减$68
查看: 2986| 回复: 17
跳转到指定楼层
上一主题 下一主题
收起左侧

[学Java/C#] 一个多态,抽象,和接口的问题

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
本帖最后由 zebointexas 于 2020-4-9 01:46 编辑

又来提智障问题了.......  

比如,Animal是Dog的父类,通常大家生产Dog是用

Animal 狗一号 = new Dog()

Dog因为继承了Animal,有Animal的所有属性,同时 --> Dog可以overrideAnimal的method (比如可以bark,跑步)+ Dog也可以有Animal没有的mothod (比如,“握爪”,并不是所有的Animal都会"握爪")

那么问题来了,Animal 狗一号 = new Dog(),这个 狗一号 ,并不能使用Dog里面有,但是Animal没有的"握爪"。这种情况下,为何大家保持 Animal 狗一号 = new Dog() 的方式来创建狗,而不用 Dog 狗一号 = new Dog() ?


那么这种生产对象的习惯,跟polymorphism多态是有什么样的关系? (polymorphism多态 = override || overload)(不熟悉oeverload的可以看这里: https://www.zhihu.com/question/35874324

====================   分割线  ====================

然后想讨论一个abstract和interface的区别。(不熟悉的可以看这里:  https://blog.csdn.net/b271737818/article/details/3950245

而关于深层次的区别:
https://www.ibm.com/developerwor ... abstract/index.html  
https://www.imooc.com/article/6601

如果abstract的目的是让用户无法生产对象,那么继承他,是要实现abstract里面所有的method,才能生产,对吗?

java.lang.Object
       java.util.AbstractCollection<E>
              java.util.AbstractList<E>
                     java.util.AbstractSequentialList<E>
                            java.util.LinkedList<E>

比如这个 java.util.LinkedList,是从Object一直继承下来的,所谓独苗一代单传。

同时 java.util.LinkedList 又实现了各种接口: Serializable, Cloneable, Iterable<E>, Collection<E>, Deque<E>, List<E>, Queue<E>  

站在架构的角度,为何来同时来用abstract和interface呢?

他们各自存在的重大意义和区别是什么呢?

============最后起一个米啊

感觉是像在路边讨米的一样 哈哈哈,谢谢各位。(也麻烦高抬贵手顶一下帖子啊 哈哈哈)

来三个放松的曲子:
小河流水: https://www.youtube.com/watch?v=lE6RYpe9IT0
咖啡Jazz: https://www.youtube.com/watch?v=uqZTrvxc-gY  
https://www.youtube.com/watch?v=lE6RYpe9IT0




评分

参与人数 3大米 +4 收起 理由
pinguin + 1 赞一个
生蚝来十个 + 1 赞一个
mniann + 2 给你点个赞!

查看全部评分


上一篇:讨论一下1060. Missing Element in Sorted Array,互相加米
下一篇:147. Insertion Sort List
推荐
putout 2020-4-11 03:15:12 | 只看该作者
全局:
Edsger.X 发表于 2020-4-10 12:20
一般声明类我们选最抽象但是支持你所需要操作的类。 --> 你说的申明类是什么意思?

比如Map map = Has ...

声明类就是变量声明时给予它的类型。
Animal doggy = new Dog();
doggy虽然是Dog实现的,但是它的声明类型是Animal。从这之后我们只把它看作为Animal,忘记它其实是个Dog。

为什么声明类要尽量选抽象?首先,我们使用其它method时,method argument一般是最抽象的。比如一个打印某List中所有元素的method:
void printList(List<...> list) ;
它只管你给它某种List就可以打印出其中所有的元素。如果定义成void printList(ArrayList<...> list) 这就不妥,因为这就排除了其它所有种类的List,但是打印所有的元素又不需要管它具体是LinkedList还是ArrayList。
同理,如果你在写一个method接受method arguments,在选类型时最好选最抽象并能完成任务的类。你如果在写printList这个method,如果之中不需要用某种特别的List的操作,当然你就不应该限制别人放List进来应该是LinkedList还是ArrayList。

其实尽量选择抽象的声明类也是约束自己的一个方法。解决问题时尽量先用抽象的方法去解决,实在不行再用具体操作。比如Map:
Map<...> map = new TreeMap<>();
这一行之后的代码都会认定map为抽象的Map,很可能只需要用Map的基本操作。如果后来我们想把它的具体实现改成HashMap(比如要更efficient),只要把这一行的TreeMap改成HashMap就行了,并且这保证代码正确因为至少在Map支持的操作上TreeMap和HashMap的外表动作相统一。如果你声明时就用了
TreeMap<...> map = new TreeMap<>();
那之后代码每一次提到TreeMap都要改成HashMap,而且不能确定这改的会不会有bug因为你可能后面有了TreeMap某个特别操作或特征在HashMap上不适用。

abstract class和interface最大的不同是抽象思维上的区分。支持一个interface代表某类拥有这个接口所有的抽象操作,但是继承一个abstract class意思是某类的本质归纳应从这个abstract class来延伸
这是什么意思?假如我有个接口“会跳”:
interface 会跳 {
   void 跳 ();
}
那什么东西会跳?人会,动物也会,机器人也会,但是除了支持这个操作以外可能这些东西都没太大相似的地方。这就是为什么在Java中典型的接口Comparable,Cloneable,Iterable都是以抽象操作为命名的。除了支持这个操作以外对子类没有任何要求。

反之,继承abstract class对于一个子类是对他本质的归纳。Dog继承Animal,因为它本质更抽象一级就应理解为动物。虽然它也继承interface 会跳,它不应本质理解为“会跳的东西”。所以abstract class所覆盖的一般是某名词,而interface所覆盖的一般是某组动词

最后你可能会问List,Map,Set是名词啊,为什么Java中它们都是interface。这是因为List应理解为“支持列表诸操作的某数据结构”,而不是说某类本质就是以列表实现的。如果后者成立,在Java中它们会继承AbstractList这个abstract class来代表他们本质是列表。这也是为什么我们可以这样写:
Queue<...> q = new LinkedList<...>();
LinkedList也支持Queue的所有操作,所以我们就把它当Queue来使,即使它本质是以列表来实现的。


评分

参与人数 2大米 +3 收起 理由
不知道小帅 + 2 给你点个赞!
vnborx + 1 赞一个

查看全部评分

回复

使用道具 举报

推荐
putout 2020-4-9 07:47:30 | 只看该作者
全局:
楼上讲的很好。补充几点:


一般声明类我们选最抽象但是支持你所需要操作的类。比如Map<...> map = HashMap<>(); 我们在这行之后不管map具体是HashMap还是TreeMap实现的,只要它能put和get就行。我们接受map为一个method argument时也一般声明为Map因为我们不管它的具体实现。而如果我们必须要用到某种特定实现支持的操作就要声明成那个子类,比如TreeMap的lowerKey。

abstract class与interface不同还有abstract class可以有member data fields,子类可以继承并读取。Interface不能定义data fields,但是可以在default实现中提供。

abstract class与子类关系一般是一父多子(一个abstract class有多种实现)。Interface与子类的关系一般是多父一子(一个实现类支持多种接口)。
回复

使用道具 举报

🔗
K哥 2020-4-9 03:19:13 | 只看该作者
全局:
頂一下吧,感覺挺有趣的問題
回复

使用道具 举报

🔗
gatechkc 2020-4-9 03:26:12 | 只看该作者
全局:
同关注,理清楚这些关系还是感觉挺难的
回复

使用道具 举报

🔗
zqyzdsjdy 2020-4-9 05:24:02 | 只看该作者
全局:
比如第一个问题吧,如果你如果只考虑狗而且认定以后都是狗那就直接Dog dog呗,但以后如果你有猫呢,如果有十种一百种动物,比如server发过来的是一百种动物的集合你可以用List<Animal>直接表示出来
回复

使用道具 举报

🔗
remarktk123 2020-4-9 06:36:26 | 只看该作者
全局:
本帖最后由 remarktk123 于 2020-4-9 07:11 编辑

1. 为什么用Animal不用狗
比如我的方法里需要call喂食(),那就声明成动物
如果我的方法里需要call汪(),那就声明成狗
如果我的方法里需要call抬腿撒尿(),就要声明成成年公狗
这里动物,狗,成年公狗都是interface,如果你的方法只需要call喂食(),而你非要声明成“2岁7个月黑色法斗”这种class,那你碰到6个月萌萌哒金毛还喂不喂了,良心不会痛么?

2. 同时用interface和abstract class的机会很多
interface 狗 {
public void 吃饭();
public void 特殊技能();
}

abstract class 抽象狗 implement 狗{
    吃法(){吃狗粮}
    abstract 特殊技能();
}

class 公泰迪 extends 抽象狗 {
    特殊技能 {日天日地日空气}
}

class 拉布拉多 extends 抽象狗 {
    特殊技能 {吃不饱}
}

你以为这就完了
class 我家拉布拉多 extends 拉布拉多 implement 萌萌哒 {
    卖萌() {蹭蹭你}
}
简单来说,接口是为了适应不同场景,类是为了继承方法的实现。比如吴彦祖可以是男人,帅哥,演员,好爸爸,所以就实现这些接口;但是他吃喝拉撒和普通人一样,所以就继承普通人这个类;普通人虽然大部分功能实现一样,但是有些方法每个人不一样,比如卖萌(),这个方法就定义成抽象方法,普通人类也就是抽象类了。
以前interface是不能有实现的,所以有个(抽象)类来继承可以减少代码量,然而现在interface有default了,抽象类可以用interface+default来实现,不过问题就变成继承多个接口发现统一方法的不同default实现怎么处理

回复

使用道具 举报

全局:
本帖最后由 LittleFishBall 于 2020-4-9 07:59 编辑

感觉一般不会 Animal dog1 = new Dog() 这样写。 而是 你有一个函数,接收 Animal Type. 比如, helloAnimal(Animal animal), 然后你把 dog1 传进去,这样可以实现多态。

“那么继承他,是要实现abstract里面所有的method,才能生产,对吗?” 回答: 不一定。 abstract class 是可以有 method implementation, 你只要保证 implement 所有父类的 abstract method.

Interface 和 Abstract 的意义在于, Java 不能多继承,也就是一个子类只能 extend 一个父类,那么怎么来 bypass 这个限制,就是让这个 子类 implement 多个 interface, 这个在java 里面是没有限制的

回复

使用道具 举报

🔗
a5066987 2020-4-9 08:10:12 | 只看该作者
全局:
我觉得Animal 狗一号 = new Dog()这种用法就隐含了当前场景下你并不需要把狗当狗这样一个意图,不然的话向上转型的开销应该要比向下转型要小吧,
Interface是为了解决多继承带来的一堆问题,比如virtual inheritance这种很哈皮的东西。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表