没有继承的 OOP 重用:“现实世界”如何实现这个实用吗?

发布于 2024-10-17 09:42:34 字数 416 浏览 2 评论 0原文

本文描述了一种我觉得很有趣的 OOP 方法:

如果对象存在为 封装和通信 通过消息?如果代码重用了怎么办 与继承无关,但是 使用组合、委托,甚至 老式的辅助对象或任何 程序员认为合适的技术? 本体并没有消失,但它 与实现分离。

我发现最令人震惊的是,无需继承或依赖于类层次结构即可重用的想法,但这有多可行呢?

给出了示例,但我不太明白如何更改当前的代码以适应这种方法。

那么这种方法的可行性如何呢?或者真的不需要更改代码,而是需要“仅在需要或最佳时使用”的基于场景的方法?

编辑:哎呀,我忘记了链接:这里是 链接

This article describes an approach to OOP I find interesting:

What if objects exist as
encapsulations, and the communicate
via messages? What if code re-use has
nothing to do with inheritance, but
uses composition, delegation, even
old-fashioned helper objects or any
technique the programmer deems fit?
The ontology does not go away, but it
is decoupled from the implementation.

The idea of reuse without inheritance or dependence to a class hierarchy is what I found most astounding, but how feasible is this?

Examples were given but I can't quite see how I can change my current code to adapt this approach.

So how feasible is this approach? Or is there really not a need for changing code but rather a scenario-based approach where "use only when needed or optimal"?

EDIT: oops, I forgot the link: here it is link

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

物价感观 2024-10-24 09:42:34

我相信您听说过“总是更喜欢组合而不是继承”。

这一前提的基本思想是将具有不同功能的多个对象组合在一起以创建一个功能齐全的对象。这应该优于从彼此无关的不同对象继承功能。

关于这一点的主要论点包含在里氏替换原理的定义中,并由这张海报有趣地说明:

里氏替换原则:如果它看起来像鸭子,嘎嘎叫起来像鸭子,但需要电池 - 你可能有错误的抽象

如果您有一个 ToyDuck 对象,从纯粹继承的角度来看,您应该从哪个对象继承?你应该继承Duck吗?不——很可能你应该从 Toy 继承。

最重要的是,您应该为代码使用正确的抽象方法(无论是继承还是组合)。

对于您当前的对象,请考虑是否存在应该从继承树中删除并仅作为您可以调用和调用的属性包含在内的对象。

I'm sure you've heard of "always prefer composition over inheritance".

The basic idea of this premise is multiple objects with different functionalities are put together to create one fully-featured object. This should be preferred over inheriting functionality from disparate objects that have nothing to do with each other.

The main argument regarding this is contained in the definition of the Liskov Substitution Principle and playfully illustrated by this poster:

Liskov Substitution Principle: If it looks like a duck, quacks like a duck, but needs batteries - you probably have the wrong abstraction

If you had a ToyDuck object, which object should you inherit from, from a purely inheritance standpoint? Should you inherit from Duck? No -- most likely you should inherit from Toy.

Bottomline is you should be using the correct method of abstraction -- whether inheritance or composition -- for your code.

For your current objects, consider if there are objects that ought to be removed from the inheritance tree and included merely as a property that you can call and invoke.

逆光下的微笑 2024-10-24 09:42:34

继承不太适合代码重用。为了代码重用而进行继承通常会导致:

  1. 具有继承方法的类不得在其上调用(违反里氏替换原则),这会让程序员感到困惑并导致错误。
  2. 当可以在十几个或更多类中的任何位置声明所需的方法时,层次结构很深,需要花费大量时间才能找到所需的方法。

一般来说,继承树的深度不应超过两层或三层,并且通常您应该只继承接口和抽象基类。

然而,仅仅为了重写现有代码是没有意义的。但是,当您需要修改时,请尽可能尝试切换到合成。这通常允许您以较小的部分修改代码,因为类之间的耦合会减少。

Inheritance is not well suited for code reuse. Inheriting for code reuse usually leads to:

  1. Classes with inherited methods that must not be called on them (violating the Liskov substitution principle), which confuses programmers and leads to bugs.
  2. Deep hierarchies where it takes inordinate amount of time to find the method you need when it can be declared anywhere in dozen or more classes.

Generally the inheritance tree should not get more than two or three levels deep and usually you should only inherit interfaces and abstract base classes.

There is however no point in rewriting existing code just for sake of it. However when you need to modify, try to switch to composition where possible. That will usually allow you to modify the code in smaller pieces, since there will be less coupling between the classes.

π浅易 2024-10-24 09:42:34

我只是浏览了一下文本,但它似乎说明了 OO 设计始终是关于什么的:继承并不意味着作为代码重用工具,松散耦合是好的。 这之前已经写了几十次了,请参阅文章底部的链接参考文献。这并不意味着您应该完全跳过继承,您只需有意识地使用它,并且仅在有意义时使用它。文章中也指出了这一点。

至于鸭子打字,我发现例子和想法有问题。就像这样:

function good (foo) {
  if ( !foo.baz || !foo.quux ) {
    throw new TypeError("We need foo to have baz and quux methods.");
  }
  return foo.baz(foo.quux(10));
}

添加三行新行只是为了报告运行时自动报告的错误有什么意义?

I just skimmed the text over, but it seems to say what OO design was always about: Inheritance is not meant as a code reuse tool and loose coupling is good. This has been written dozens times before, see the linked references on the article bottom. This does not mean you should skip inheritance entirely, you just have to use it conciously and only when it makes sense. The article also states this.

As for the duck typing, I find the examples and thoughts questionable. Like this one:

function good (foo) {
  if ( !foo.baz || !foo.quux ) {
    throw new TypeError("We need foo to have baz and quux methods.");
  }
  return foo.baz(foo.quux(10));
}

What’s the point in adding three new lines just to report an error that would be reported by the runtime automatically?

撑一把青伞 2024-10-24 09:42:34

继承是根本

,没有继承,就没有OOP。

原型和委托可以用来实现继承(就像在 JavaScript 中一样),这很好,并且在功能上等同于继承

对象、消息和组合,但没有继承是基于对象的,而不是面向对象的。 VB5,不是Java。是的,可以做到;计划编写大量样板代码来公开接口和转发操作。

那些坚持认为继承是不必要的,或者继承是“坏”的人正在创造稻草人:很容易想象继承被滥用的场景; 这不是对工具的反映,而是对工具用户的反映

Inheritance is fundamental

no inheritance, no OOP.

prototyping and delegation can be used to effect inheritance (like in JavaScript), which is fine, and is functionally equivalent to inheritance

objects, messages, and composition but no inheritance is object-based, not object-oriented. VB5, not Java. Yes it can be done; plan on writing a lot of boilerplate code to expose interfaces and forward operations.

Those that insist inheritance is unnecessary, or that it is 'bad' are creating strawmen: it is easy to imagine scenarios where inheritance is used badly; this is not a reflection on the tool, but on the tool-user.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文