工作好多年有可能还未真正了解接口和抽象类

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/a9/a9f06646997fe4d6c422ff5b0b864238.png","alt":"image","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"抽象类和接口的定义和区别?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"抽象类在面向对象编程中解决了什么问题?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"接口在面向对象编程中解决了什么问题?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"如何决定该用抽象类还是接口?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"如果使用的语言不支持抽象类和接口,该如何应对?"}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"link","attrs":{"href":"#抽象类","title":null}},{"type":"text","text":"抽象类"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在面向对象编程的语言中,多数都添加了对抽象类和接口的支持,比如最常用的java,C#等语言。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":" //抽象类\n public abstract class Human\n {\n //抽象方法\n public abstract string Gender();\n //属性\n public string Name { get; set; }\n //方法\n public int GetAge()\n {\n return 1;\n }\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以上是一个普通的抽象类的定义,具体怎样使用,度娘有一大堆结果,其实总体来说抽象类主要有以下几点特征:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"抽象类不能被实例化,只能被继承。也就是说如果 New Human()会报编译错误"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"抽象类也是类,可以包含属性和方法,方法可以包含实现,也可以不包含,不包含实现被称为抽象方法。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"子类继承抽象类,必须要实现定义的所有抽象方法,不然编译器会报编译错误。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"抽象类本质上还是类,只不过是一种不能被实例化的特殊类而已,但是在面向对象的设计过程中却起着非常重要的地位,本质上抽象类体现的是is-a的关系,就像上边定义的抽象类一样,Human类型抽象的是人类,假如我定义一个菜菜的类型来继承这个类型"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":" public class CaiCai : Human\n {\n public override string Gender()\n {\n return \"男\";\n }\n\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"CaiCai这个类必须要提供抽象方法的实现才可以通过编译。抽象类的产生是面向对象开发思想的延伸,是解决代码复用问题的一个方案,更是把代码进行抽象化的一个结果。抽象类的设计思想是自下而上的,也就是说设计上应该先有子类,当子类逐渐增加,进而抽象出共用特性而产生抽象类。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"说到这里,好多同学会问,如果我不用抽象类做父类也可以啊。不错,普通的类当然也可以代替抽象类的地位。但是有几点就看起来比较奇怪了"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"父类也可以进行实例化了,但是其中要抽象的方法看起来就比较怪了,因为这些方法只有子类中才有明确的定义,比如 以上代码中Human这个类如果修改为普通类型,那方法Gender()该返回什么内容呢?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"在编译期间,如果子类没有实现父类的方法是不会报错的,这就加大了排查问题的难度,如果需要重写的方法很多,之后排查问题会非常头疼"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"抽象出来的父类如果可以被实例化,这本质上违反了面向对象的思想,毕竟父类是一个抽象化的概念,被实例化之后代表着什么比较令人困惑"}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"link","attrs":{"href":"#接口","title":null}},{"type":"text","text":"接口"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接口在系统设计中,最重要的作用就是解耦。你应该听过不止一次的“面向接口编程”和依赖倒置等思想,这些也是面向对象设计思想的一种体现。接口本质上是抽象出来的对象的行为,或者叫做契约。在面向接口开发中,调用者不关心接口的实现,而是依赖于接口的定义,接口定义的稳定性代表着一个系统的稳定性,如果一个系统对外的接口定义有问题,那这个系统多半是会死人的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":" public interface IHuman\n {\n //接口行为定义\n void Walk();\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以上只是一个简单接口的定义而已,接口的抽象小到可以是一个对象的行为抽象,大到可以是一个服务的行为抽象,更有可能是一个系统的行为抽象,所以接口是一个很泛的概念,但是本质上还是反应的是面向对象设计理念。由于接口是行为的定义,所以就决定了它有以下特点"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"接口只能定义行为,不能包含行为的实现"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"类型继承接口的时候,必须要实现接口的所有行为"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"接口不同于类,不能包含属性"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由于接口体现的是行为准则,所以接口在定义的时候也可以利用面向对象设计理念,当多个不同接口定义了相同的行为,可以考虑抽象出更上层的接口来实现行为的复用。"}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"link","attrs":{"href":"#写在最后","title":null}},{"type":"text","text":"写在最后"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"抽象类和接口都是对象的抽象行为产生的,只不过抽象类更加侧重于 is-a 的关系,它实现了代码复用,而接口更加侧重于行为的抽象(has -a),举一个很简单的栗子,如果设计一个鸟类的抽象该怎么做呢?不同的鸟可能羽毛的颜色不一样,像这样的属性可以利用抽象类,不同的鸟类可能会有不同的飞行行为,这样行为类的抽象利用接口来实现更加合适。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"无论是接口还是抽象类,在代码层次上体现的是上下级关系,就算一个编程语言没有提供接口和抽象类的定义,只要能实现对象上下级关系,原理上也可以实现面向对象编程。编程的抽象思想始终在围绕着上下,内外这几个维度在合理的进化着。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"说到接口的定义,其实还可以在泛化一下,接口中只有行为方法的定义,在一些不支持接口的编程语言中,可以把只包含方法的类看做接口的抽象定义,这在设计理念上是说的通的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在继承层次上和设计流程上,抽象类是一种自下而上的设计思路,先有子类的代码,当子类逐渐增多,才会抽象出更加上层的父类。而接口不同,面向接口编程是一种自上而下的设计思路,先抽象出行为契约,然后才是实现。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"更多精彩文章"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&album_id=1342955119549267969&__biz=MzIwNTc3OTAxOA==#wechat_redirect","title":null},"content":[{"type":"text","text":"分布式大并发系列"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&album_id=1342959003139227648&__biz=MzIwNTc3OTAxOA==#wechat_redirect","title":null},"content":[{"type":"text","text":"架构设计系列"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&album_id=1342962375443529728&__biz=MzIwNTc3OTAxOA==#wechat_redirect","title":null},"content":[{"type":"text","text":"趣学算法和数据结构系列"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&album_id=1342964237798391808&__biz=MzIwNTc3OTAxOA==#wechat_redirect","title":null},"content":[{"type":"text","text":"设计模式系列"}]}]}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f8/f8af5984765a267892bf1a1272272625.png","alt":"image","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章