• Smallfly
    2019-11-14
    争哥对面向对象的总结完美符合 What/How/Why 模型,我按照模型作下梳理。

    ## 封装
    What:隐藏信息,保护数据访问。
    How:暴露有限接口和属性,需要编程语言提供访问控制的语法。
    Why:提高代码可维护性;降低接口复杂度,提高类的易用性。

    ##抽象
    What: 隐藏具体实现,使用者只需关心功能,无需关心实现。
    How: 通过接口类或者抽象类实现,特殊语法机制非必须。
    Why: 提高代码的扩展性、维护性;降低复杂度,减少细节负担。

    ##继承
    What: 表示 is-a 关系,分为单继承和多继承。
    How: 需要编程语言提供特殊语法机制。例如 Java 的 “extends”,C++ 的 “:” 。
    Why: 解决代码复用问题。

    ##多态
    What: 子类替换父类,在运行时调用子类的实现。
    How: 需要编程语言提供特殊的语法机制。比如继承、接口类、duck-typing。
    Why: 提高代码扩展性和复用性。

    3W 模型的关键在于 Why,没有 Why,其它两个就没有存在的意义。从四大特性可以看出,面向对象的终极目的只有一个:可维护性。易扩展、易复用,降低复杂度等等都属于可维护性的实现方式。
    展开
     8
     306
  • №修罗★幻影
    2019-11-13
    Java 不支持多重继承的原因
    多重继承有副作用:钻石问题(菱形继承)。
    假设类 B 和类 C 继承自类 A,且都重写了类 A 中的同一个方法,而类 D 同时继承了类 B 和类 C,那么此时类 D 会继承 B、C 的方法,那对于 B、C 重写的 A 中的方法,类 D 会继承哪一个呢?这里就会产生歧义。
    考虑到这种二义性问题,Java 不支持多重继承。但是 Java 支持多接口实现,因为接口中的方法,是抽象的(从JDK1.8之后,接口中允许给出一些默认方法的实现,这里不考虑这个),就算一个类实现了多个接口,且这些接口中存在某个同名方法,但是我们在实现接口的时候,这个同名方法需要由我们这个实现类自己来实现,所以并不会出现二义性的问题。
    展开
     13
     209
  • 哥本
    2019-11-13
    我理解的四大特性
    封装:加装备(添加盔甲)
    继承:师傅掌对掌传输武功(毫无保留)
    抽象:从道到术,柳叶能伤人
    多态:奥特曼变身。
     11
     32
  • 拉格朗日的忧桑
    2019-11-13
    这是迄今讲面向对象特性最深刻的,没有之一

    作者回复: 😄 多谢认可

    
     26
  • 小白
    2019-11-13
    go语言的“隐藏式接口”算是多态中duck-typing的实现方式吧
     4
     17
  • 丁丁历险记
    2019-11-14
    好久没复杂这些基础知识了,借今天写笔记的时间过足瘾。我就菜鸟一个,也深知言多必失,肯定有瞎扯的地方,还请指正,我好迭代。
    1 封装
    常见编程语言通过 public protected privite 来支持
    封装的意义 。
    关掉直接操作数据的口子,让数据的修改更贴合真实业务。
    例如:创建时间,就没有修改数据的场景。
    钱包的钱数,只能通过增加,减少接口进行调整,不开放直接设置金额的接口(口子一开,对账就是个麻烦事)
    另一个意义,调用类,没有必要知道太多的实施类的具体实现细节。让操作更为简单。
    个人思考:
    封装就是让代码遵守开闭原则的重要手段。
    当调用类,关注过多实施类的继节时,一个需求的变化,可能引发多个依赖模块都发生了级联的改动,而一但调用类过度的知道了太多了实施类的细节(然后各种调用类代码再一散落),这时程序也相应地变得出各种毛病出来,既然这样,把实现的方法封装起来多好,让调用端少操点心。
    Law of Demeter 有个别名,就叫最少知道原则,争哥说的第二个意义,感觉就是在描述遵守迪米特法则的好处.
    再乱想一下, 人体,不就是最好的的封装么, 给你物料的入口(吃),出口(拉),还给你调节增强的接口(训练) 有多少人,并不知道其内部细节,不照样过着精彩的一生。 还有,调用类,总想知道更多被调用类的信息,以期更精准的控制,这种代码风格,就是完美主义病,而完美主义的并发症就是拖延症,以及极高的复杂度造成项目越写越混乱。
    2 抽像。
    抽像讲的是如何隐藏信息,而抽像讲的是隐藏方法的具体实现,让调用者只关心方法提供了哪些功能即可。
    通常借 interface 和 abstract class 来实现 抽像这一特性。当implement 某接口时,只要知道接口干了啥,即可,无需要关心实施类的细节实现。
    抽你的意义,能解决啥问题。
    1 处理复杂性的有效手段。人脑承受信息有限,抽像做为不关注实现细节的套路,正好管用。
    2抽像指导了很多的oo原则 , 凡时对实现进行封装抽离的,都可以叫抽像,例如malloc()
    3 定义类时,要有抽像思维,不要在方法中,暴露太多细节。(建议一层抽象层,让功能分解得更细,让意图和实现分享)
    个人理解
    (抽象处理的复杂度是人月神话里描述 的本质复杂度(Essential Complexity), 也是尊重人脑的认知学的 ,大脑的特性是很烂的( 抽像的工具包记重点,归纳特性,忽视细节),(推荐阅读google 整理术)
    再瞎想一下,抽像是将很多的知道点给封装起来了(encoding 成为一个模型) , 归纳法便是抽象的重要实现套路,也是支撑及发展文明的利器。 抽像在开发中的意义 ,是让具体的实施类,在合适的场所下编写 (最好满足sru),然后通过合理的ood ,去调用或运行时create 具体的子类对象,去实现。 拜抽象所赐,一种各有分工,又能有序协同的场景就出来了
    其三,个人套路包,我沟通时,当和建议相同方向时,就往抽像了说,当想有差异时,就很细节说。 (套路是双韧剑,就看你如何用了),我个人发现很多营销大的套路,抽像来看和传销是一至的,有些技术大牛的工作套路,和某著名贪官一模一样。(例如,把话说明白了再干,明确职责)
    笔记下(下)
    3继承
    继续用来表示类之间是 is -a 关系。
    猫是动物,于是就拥有的动物的自带属性行为。(移动速度,移动距离) 进一步的,动物属生物(于是) 有了生命的共有属性,年龄
    有些语言单继续,有些多继承。
    意义 和解决问题。
    1 符合认知美感 。
    2 减少重复coding .
    问题: 重要隐患,父子类,大量方便藕合。
    个人理解。
    继续和不停的复杂粘贴代码是两个极度,复制代码虽散但各管各的,继续父一改,子跟着改,而复制代码这事,是问题是,实现一个细节后,其它的相联代码,都要不停的改。而继随相反,一改全刷了,除非你子类完全重写了,而一些不成熟的开发,前期的父类往往考虑不周,后期一折腾,悲剧从此开场。
    再者 复制粘贴代码,两段代码关联太轻,基本上就是要一处一处的改,而复制这事,就关联得太重了。 一但重了,就往往产生大量的不必要的负担。 我学设计模式最开心的就是,基于原则,而不是基于规则,不同场景就用不同的套路。
    基于职责太重这事,我是很反感用多重继续的。 需要啥,再组合一个类多好。 多关联一个类,死不了人的。 搞出菱形继随这种蛋疼的东西,又要不停的去关注细节,活着会很累的
    4 多态。(个人觉得oo 中最有趣的一块)
    多态指子类替代父类。
    三种语法机制。(父可以)
    实现多态,除继续外,还有利用接口类语法, duck-typing
    个人理解:理解不深。有感觉描述不出来,就觉得,继续把事搞死了,多态就要死的东西搞活。 于是支持这种把事搞活的套路出来。
    展开
     2
     13
  • weiguozhihui
    2019-11-13
    c 语言通过结构体来实现封装,只是c 的结构体没有关键字来控制结构体内部成员的访问权限问题,属于一种比较粗的封装。另外C中通过void*+结构体+函数指针也是可以实现多太的。Linux内核代码好多都是用了面向对象编程思想。C++中引入public protected private 关键字来进行访问控制权管理。C++中没有Java中的interface 关键字来描述接口类,但也是可以通过虚函数基类来进行的Java中的接口类的。C++是直接支持多继承的,但这个特性也被好多人诟病。
     1
     12
  • 每天晒白牙
    2019-11-13
    专栏中有个思考题是 java 为何不支持类多继承?却支持接口的多继承?
    而有些语言如python是支持多继承的?
    首先java类支持多继承的话,两个父类有同名方法,在子类中调用的时候就不知道调用哪个了,出现决议(钻石问题或菱形问题)问题
    而接口支持多继承因为接口定义的方法不能有方法体,所以不会出现决议问题。
    而从jdk1.8开始,接口可以有默认方法(方法要用default标识),必须要有方法体,这样在接口多继承上不也会有决议问题吗?其实你去试下就知道了,java发现这种情况,会通过让你强制在子接口中重写这个默认方法,这样就不会有决议问题了

    python支持多继承因为它通过MRO解决的,pythoner应该懂,我是不太懂,感兴趣的可以去研究
    展开
    
     11
  • 划时代
    2019-11-13
    话题一:
    C++语言的多重继承,存在三层继承关系时,采用virtual继承方式,形成菱形继承。标准库中的iostream类就存在多重继承关系,见图http://www.cplusplus.com/img/iostream.gif。
    话题二:
    C++语言的多态实现方式比较丰富,除了类中的virtual函数实现运行期多态以外。还支持编译期多态(模板元编程),不仅能够动态改变对象执行的函数,还能动态改变对象的定义类型。
    
     9
  • 业余草
    2019-11-13
    是时候抛出这道难住99%的程序员的设计模式面试题了!
    https://mp.weixin.qq.com/s/9SBV9ZycAQY82BacYICY2w
     19
     9
  • 初心
    2019-11-16
    多态一句话,现在调用将来
    
     8
  • zcdll
    2019-11-15
    1. 你熟悉的编程语言是否支持多重继承?如果不支持,请说一下为什么不支持。如果支持,请说一下它是如何避免多重继承的副作用的。
        1. JavaScript 不支持多继承,多继承理论上都存在“菱形问题”,也就是说如果 class D 继承了 class B 和 class C,class B 和 class C 都继承了 class A,class A 中有一个方法 add,B 和 C 都重写了 add 方法,当 D 去调用 add 方法时 就会出问题,不知道调用哪个方法了。
        2. 理论上是可以通过 Mixin 的方式来实现多继承。
        3. 通过一些 合并 算法来“部分”解决“菱形问题”
        4. 参考 JavaScript中的“多继承” [https://juejin.im/entry/5ac46b6c5188255570063b71](https://juejin.im/entry/5ac46b6c5188255570063b71)
    2. 你熟悉的编程语言对于四大特性是否都有现成的语法支持?对于支持的特性,是通过什么语法机制实现的?对于不支持的特性,又是基于什么原因做的取舍?
        1. JavaScript 支持封装,抽象,继承,多态
        2. 封装 ES6的话,通过 public protected private 等关键字来实现,ES5 的话通过 “函数作用域”,this,原型链来实现,ES6 的 class 本质上也是 function 的语法糖。
        3. 抽象 可以通过 this指针 和 原型链 的形式来实现
        4. 继承 通过 原型链 来实现,或者说基于封装的特性来实现
        5. 多态 通过原型链 的方式,子类覆写父类的方法来实现
    展开
     1
     8
  • 晨风破晓
    2019-11-13
    PHP不支持多继承,具体为什么还没了解过,四大特性都是有现有语法支持的;看完这堂课,貌似对多态还不是很理解
     7
     7
  • 见哥哥
    2019-11-13
    我们使用Java已经很长时间了,我们有多少次因为缺少多重继承而面临困难呢?
    我个人的经验是一次都没有。因为多重继承很少有机会被用到,所以更安全的做法是去掉它而保持简单性。
    就算是碰到需要多重继承的情景,我们也可以找到替代方法。
    我的观点是,去掉对多重继承的支持不是Java的缺陷,对开发者来说是件好事。
     2
     7
  • 秉心说
    2019-11-13
    多继承会带来菱形继承的问题。例如一个类的两个父类,都继承了同一个祖父类,两个父类都 override 了祖父类的方法,这时候孙子类就不知道如何调用了。

    Java 8 的 interface 可以有方法默认实现,这应该可以算是曲线救国的多继承吧。
    
     7
  • Paul Shan
    2019-11-13
    猫不是爬行动物,:).
    
     6
  • 李湘河
    2019-11-13
    示例代码自己运行了麽,虽说是将设计思想、设计模式,但是代码很多错误呀,像多态示例代码,父类私有属性在子类继承中能直接用吗?

    作者回复: 已经修改成protected的了。代码自己改改,可以运行的。但代码的作用主要还是辅助解释理论,所以有所删减,也是考虑到文章篇幅的问题。

     1
     4
  • 秋惊蛰
    2019-11-13
    试着说一下Python吧
    - 抽象:抽象是编程语言的共有特点,甚至是计算机科学的特点,从变量,函数,类,模块,包等概念都是不同层次的抽象。抽象和把大象装进冰箱分三步是一个道理,它给出了思路,指明了方向,省略了细节。我们用层层抽象来应对计算机系统的复杂性。Python主要的抽象工具是函数和类,模块和包也算吧,毕竟也是隐藏了细节。
    - 封装:Python不支持严格意义上的封装,没有private, protected等访问修饰符,这样做是为了保证动态语言最大的灵活性,同时Python里很多理念都是约定大于定义的,私有的属性需要大家守约,不要去随意访问,这也是Python被吐槽的地方吧,大型项目约束力不够。
    - 继承:Python支持多重继承,主要是因为它没有类似于Java的“接口类”的语法吧,用多重继承可以定义一些纯功能性的类,减少类的层级。
    - 多态:Python的多态就是鸭子类型了,鸭子类型的背后是所谓“协议”,协议是非正式的接口,是一种特性,表现为一个或多个相关的方法,比如迭代器协议,序列协议。实现了迭代器协议就和Java中实现了Iterator接口一样。
    展开
    
     4
  • ldd
    2019-11-19
    话题1:
    Objective-C不支持多继承,OC的方法调用是基于消息机制,是基于方法名调用的,而且是发生在运行时而非编译时,很难解决多个基类可能导致的二义性问题。
    话题2:
    封装:@private、@protected、@public 表作用域的关键字,而且还可以用.h、.m机制实现。
    抽象:protocol 协议来实现。
    继承:简单的 Child : Parent 来实现,内部其实用 isa 指针来实现的。
    多态:继承、protocol 都可以实现

    番外:OC也可以实现多继承,可以用消息转发机制去实现。但本人觉得多继承好像确实不是很实用,之前看 c++ 文档也不建议多用,很想听听争哥对多继承的态度☺️
    展开
    
     3
  • 小妖
    2019-11-21
    我觉得文中对多肽的定义有问题,多肽不仅是只子类替换父类(父类对象引用子类对象),也包括父类(代理类)可以在某些时候代替子类作为参数传递(继承的方式实现参数代理),更直观的表现是实现类替换接口(接口引用接口的实现比如 : LIst<String> list=new ArrayList<>();),这听起来有点像是抽象,实际上抽象的很多情况下是依赖多肽的,比如,方法接口接口作为参数,而不必接收具体的类这体现了抽象,但更体现了多肽…………求交流

    作者回复: 你举的例子不还是子类传递给父类吗

    
     2
我们在线,来聊聊吧