“继承” 怎么就变成了“根据一个对象的实现定义了另一个对象的实现”? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
huzhikuizainali
V2EX    Java

“继承” 怎么就变成了“根据一个对象的实现定义了另一个对象的实现”?

  •  
  •   huzhikuizainali 2023-10-14 23:39:52 +08:00 via iPhone 1271 次点击
    这是一个创建于 732 天前的主题,其中的信息可能已经有所发展或是发生改变。

    理解类继承和接口继承(或子类型化)之间的差别也十分重要。类继承根据一个对象的实现定义了另一个对象的实现。简而言之,它是代码和表示的共享机制。然而,接口继承(或子类型化)描述了一个对象什么时候能被用来替代另一个对象------《设计模式》

    <>接口不就是特殊的抽象类么(相对于抽象类而言,接口只声明方法,不声明属性或字段)。一个具体类实现接口,不就是一个类继承“接口”后实现了接口中声明过的方法么,这件事怎么就变成了“一个对象什么时候能被用来替代另一个对象”?

    其次类类的继承怎么就变成了“根据一个对象的实现定义了另一个对象的实现”。继承这件事不就是子类“继承”了父类中的属性和方法和方法么,怎么就变成了“根据一个对象的实现定义了另一个对象的实现”?

    netabare
        1
    netabare  
       2023-10-14 23:53:12 +08:00   1
    光是看 op 的描述感觉都要长脑袋了。

    建议用比较清晰的专业术语来描述一下,比如子类型( subtyping ),虚函数的派发机制(比如 dynamic dispatch ),还有早期绑定和多态( polymorphism )。说不定就没有这些疑惑了。

    现在看到这种模糊不清似是而非的语句真是头大。
    codehz
        2
    codehz  
       2023-10-15 00:02:15 +08:00
    主要是混淆了“继承/派生”和“子类型”的两个关系
    它们原则上应该是正交的关系,不过在 java 里,类继承同时包含了学术意义上的“继承/派生”和“子类型”,实现接口(不考虑默认实现这个新玩意)则只包含“子类型关系”
    也就是说,理论上类型 S 和类型 T 的关系有这 4 种可能性
    1. S 既不是 T 的子类型也不是派生类型
    2. S 是 T 的子类型,但不是 T 的派生类型
    3. S 不是 T 的子类型,而是 T 的派生类型
    4. S 既是 T 的子类型又是派生类型
    而 java 禁止了 3 这个选项
    子类型关系,可以简化为 is-a 关系,就是你所看到的“替代另一个对象”的描述
    继承关系,才是复制/共享实现的含义,也就是“根据一个对象的实现定义了另一个对象的实现”
    所以 java 的类继承是做了两件事
    1. 复制父类的实现
    2. 将自身标记为父类的子类型
    huzhikuizainali
        3
    huzhikuizainali  
    OP
       2023-10-15 00:23:00 +08:00 via iPhone
    @codehz 谢谢回复。请教一下
    1 、“ S 是 T 的子类型,但不是 T 的派生类型”,这个用代码怎么实现?我的面向对象知识主要来自于 Matlab ,顺带看了一下 C++和 C#。从没遇到这种情况。

    2 、“ 所以 java 的类继承是做了两件事
    1. 复制父类的实现
    2. 将自身标记为父类的子类型”

    因为接口不存在任何“方法”的实现,只有方法的声明。所以不存在“复制父类的实现”这件事。所以当一个类 A 实现了接口 B ,并不能说 A 继承了 B ,我这么理解对么?


    另外,无论是“类的继承”还是“接口继承”。这里面都没有对象什么事情啊。我完全可以不实例化任何一个对象就完成类的继承,或接口的实现。《设计模式》中为什么总说“对象”如何如何?我觉得这里完全没有对象什么事情啊!
    netabare
        4
    netabare  
       2023-10-15 02:52:59 +08:00   1
    @huzhikuizainali 如果是 Java 语境里的「继承」关系,一个接口不能被具体实例化,接口和具体类之间的关系当然不是继承关系而是典型的子类型关系。codehz 的回复应该很清楚了。所以您应该知道前面问题怎么用代码来写了。

    而您的直觉也是正确的。

    我重新想了一下,或许这里讨论的是那种典型的 class extends 关系的,也就是父类先调用构造器后子类再调用构造器,然后逐个字段填入属性的这套过程。如果只从 Java 的角度很狭义地考虑的话,那么这个过程里面确实和对象有一点关系调用构造器后会创建一个对象。或许,他想介绍一个子类对象可以被强转为父类的对象。这是我能想到的所有东西了。

    但是这个提法显然是有问题而且很含糊不清的。子类型或者继承/派生关系也确实不需要牵扯进来具体的对象的概念。说实话,关于类继承和接口继承,我觉得那两句话里面的对象换成类型,也就「类继承根据一个类型的实现定义了另一个类型的实现」,「接口继承描述了一个类型什么时候能被用来替代另一个类型」,反而更准确一些。不知道是书本翻译的问题还是原书对一些概念的解释不清楚。

    Java 的 OOP 和 C#的 OOP 没有本质上的区别,可能和 C++的有点区别就是。
    Al0rid4l
        5
    Al0rid4l  
       2023-10-15 13:39:29 +08:00
    @huzhikuizainali

    "S 是 T 的子类型,但不是 T 的派生类型" JS/TS 的结构子类型

    "一个对象什么时候能被用来替代另一个对象" 大概是想表达里氏替换...也许用"一个变量什么时候能被用来替代另一个变量" 会显得更加合适

    "根据一个对象的实现定义了另一个对象的实现" 其实也可以参考 JS 原型链...

    你说"一个类 A 实现了接口 B, 或者 A 继承了 B" 广义上来讲都没什么问题, 纠结这些字眼意思不大, 没事就继承都是那个年代推 OOP 给 C++/Java/C# 掺的屎, C++ 和 C# 还稍好点...
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1184 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 23:32 PVG 07:32 LAX 16:32 JFK 19:32
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86