这个问题是关于任何静态类型语言的OOP。假设我有两个类,其实例保持彼此的指针/引用。在我的例子中,一个类是一个容器,另一个类是一个包含对象的包装器,它包含一个指向它所在容器的指针。
class Container {
Element[] elements;
}
class Element {
// ... data...
Container holds_me;
}
Container
的构造函数创建一个Element
对象来包装每个包含的对象,并将它们的holds_me
指针设置为自己。
现在我想继承这些类。我想要一个DerivedContainer
类,它继承自Container
并包含DerivedElement
个对象,其中DerivedElement
继承自Element
并引用包含DerivedContainer
的对象宾语。这样做的正确方法是什么(或者做错了什么)?
最直接的事情是DerivedContainer
的构造函数创建DerivedElement
并将它们存储在elements
中,并将它们的holds_me
指针设置为自身。然后,Container
和Element
的所有方法都可以使用,但DerivedContainer
和DerivedElement
中定义的任何新方法都必须向下转换elements
中保存的对象和holds_me
以便在它们上调用未在基类中定义的任何新方法。这看起来不太漂亮;所以我想知道,有更好的解决方案吗?
答案 0 :(得分:1)
是的,这是正确的方式,没有任何更多的信息,恕我直言。如果您认为Element中的所有方法都可以应用于每个元素,那么这是有意义的,但是应该知道任何有关Derived功能集的仅类是(理想情况下)DerivedElement和(如果需要的话) )DerivedContainer。换句话说,对于其他任何人来说,元素和容器只是 元素和容器。
您有时可以使用模板(C ++)或泛型(Java)做得更好,因为这些功能背后的想法是Container<Element>
知道它包含元素而Container<DerivedElement>
知道它持有DerivedElements,但是如果你有一个异构的Container,你真的必须让每个子类通过尝试向下转换来处理派生的功能。
答案 1 :(得分:1)
如果您的语言支持,您可以使用泛型/模板。 Container类可以将Elements类作为参数化类型。这样,你就可以忘记向下传播元素。
答案 2 :(得分:0)
如果有人感兴趣,我已经意识到可以使用抽象类型在这里做更多或更少的事情。这是一些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
的任何实例化属于该类型{ {1}}(由E
的某些实现实例化。)
Container