📣 独立日限时特惠: VIP通行证立减$68
12
返回列表 发新帖
楼主: zebointexas
跳转到指定楼层
上一主题 下一主题
收起左侧

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

全局:
插个眼,感觉内容不错,醒了再看
回复

使用道具 举报

🔗
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-11 03:20:31 | 只看该作者
全局:
Edsger.X 发表于 2020-4-10 12:21
就是说,可以将来表示方便,可以直接放到List里面。

那么,如果这个Dog,就是Dog,还能放到List吗?

Dog可以直接放入List<Animal>,但是放入后我们就忘记了它的Dog本质(除非后面用instanceof)。

那为啥不就用List<Dog>呢?因为List<Animal>是放进去容易拿出来难,而List<Dog>是放进去难拿出来容易。

如果我们用List<Animal>,它可以存储各种不同动物,我们也可以放入各种不同动物,但是拿出来时候我们不知道各个元素具体是什么动物。
如果我们用List<Dog>,拿出元素时我们肯定拿出来的是狗,但是这个List只能存狗,你有个动物想放进去必须确认是狗了它才让你存。


回复

使用道具 举报

全局:
抽象不应该依赖于具体,具体应该依赖于抽象。
回复

使用道具 举报

全局:
你如果理解面向接口编程就容易理解为什么需要多态,抽象和接口了。形式上就是为了使父类的引用可以持有子类的实例,目的是为了隔离变化,解耦合。
并且接口有两个方向,一个是client定义,你来实现。另一个就是你定义,client来实现。这样定义接口的人,知道接口的签名,就可以调用了,具体怎么实现根本不关心。这样就把变化隔离开来了。比如你定义了个接口,要求对方返回一个ArrayList,后来对方业务逻辑变了,都开始用LinkedList了,没有办法返回给你ArrayList,而你只关心一个get,最后他那边的change导致了你的代码也要改。但是如果一开始定义一个List类型,他改成LinkedList返回,也没有影响你的的代码,因为get方法就是两种list共同抽象出来的。小项目里,你看不到这么做有什么优势,如果一系统尤其是sdk,client成千上万,sdk的一个小改动,可能都要导致所有的client重构,那这个sdk就完犊子了。
回复

使用道具 举报

全局:
Interface定义action,abstract定义object,用途不一样啊

回复

使用道具 举报

地里匿名用户
🔗
匿名用户-49ULY  2020-12-1 03:56:50
我觉得去上一下课程就好了
回复

使用道具 举报

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

本版积分规则

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