从链接类继承
这个问题是关于任何静态类型语言的OOP。假设我有两个类,它们的实例维护着彼此的指针/引用。在我的情况下,一个类是一个容器,另一个类是一个包含对象的包装器,它包含一个指向它所在容器的指针。从链接类继承
class Container {
Element[] elements;
}
class Element {
// ... data...
Container holds_me;
}
的Container
构造器创建一个对象Element
给每条包含的对象,并设置其holds_me
指针本身。
现在我想从这些类继承。我想要一个DerivedContainer
类,它从Container
继承和包含DerivedElement
对象,其中从Element
DerivedElement
继承,是指含DerivedContainer
对象。什么是正确的方式来做到这一点(或者是错误的做法)?
最简单的事情是为DerivedContainer
的构造函数来创建DerivedElement
S和它们存储在elements
及其holds_me
指针设置为自身。随后的Container
和Element
所有的方法都可以工作,但在DerivedContainer
和DerivedElement
定义的任何新的方法将不得不垂头丧气,以调用未在基类定义它们的任何新方法elements
和holds_me
举行的对象。这看起来不太漂亮;所以我想知道,有没有更好的解决方案?
是的,这是做的,没有任何的更多信息,恕我直言,以正确的方式。这是有道理的,如果你认为所有的元素的方法可以应用到每一个元素,但只类应该知道的派生的功能集(理想情况下只)DerivedElement和(如有必要)DerivedContainer什么。换句话说,对其他人来说,元素和容器只有元素和容器。
有时您可以使用模板(C++)或泛型(Java)做一些更好的工作,因为这些功能背后的想法是,Container<Element>
知道它存放元素,而Container<DerivedElement>
知道它拥有DerivedElements,但是如果您拥有一个异构的Container,你必须让每个子类通过尝试向下转换来处理派生的功能。
好的,谢谢。我希望派生类可以以某种方式确保它们的引用仅指向其他派生类。 – 2011-06-01 22:22:16
如果您的语言支持,您可以使用泛型/模板。 Container类可以将Elements类作为参数化类型。这样,你可以忘记向下转换元素。
但是'Container
是的,但这真的有必要吗?凭借原始设计,无论内容如何,Container都是一个容器。它所包含的元素可以构成一个类的层次结构,但是对于泛型设计来说,这仍然是正确的。我不明白为什么要将Container
从我的示例中可能不太清楚。我并不打算让Container成为一个通用的容器对象;在我预期的应用程序中,它更具体一些_happens_还包含一堆元素,DerivedContainer以不同于包含不同类型元素的方式扩展Container的功能。 – 2011-06-03 04:07:49
如果有人有兴趣,我已经意识到,它可能做更多或更少什么,我本来想在这里使用抽象类。下面是一些Scala代码:
abstract class Container { ctnr =>
type E <: Element
class Element { this : E =>
// data
def holds_me = ctnr
}
var elements : Array[E]
}
原始容器是含有一个嵌套类元素和一个抽象类型元素的抽象类。子类型断言E <: Element
需要E
始终是Element
一个子类,而自我引用this : E =>
力量Element
任何实例属于类型E
(由Container
一些实施为实例)。
class ContainerImpl extends Container {
type E = Element
// initialize 'elements' using 'new Element()'
}
abstract class DerivedContainer extends Container {
override type E <: DerivedElement
class DerivedElement extends Element { this : E =>
// more data
}
}
class DerivedContainerImpl extends DerivedContainer {
type E = DerivedElement
// initialize 'elements' using 'new DerivedElement()'
}
只是一个建议 - 您使用双链接的连接可能最终成为问题。如果你的容器类有一个静态查找方法“findContaienrWith(object)”,它可能会减少你稍后会遇到的一些复杂性。此外,该方法可以在您添加需求时重新实现(例如,您需要两个容器容纳相同对象或类似令人讨厌的情况)。 – 2011-06-01 21:48:21