【问题标题】:Why aren't Constructor Inherited?为什么不继承构造函数?
【发布时间】:2012-02-20 15:13:58
【问题描述】:

作为后续问题,发送至Base Class Only Methods

父方法由其后代继承。

为什么构造函数(例如 New())不是? 在我看来,这似乎破坏了继承。

是否有某处将其标记为特殊的属性? (如果是的话是什么?)

请解释一下发生了什么。

【问题讨论】:

  • Can you inherit a sub new (Constructor) with parameters in VB? 的可能重复项——长话短说,如果您想“链接”它们,请尝试在继承的构造函数中使用 MyBase.New(...)
  • 既然Derived是Base,它的(Base)应该存在于Derived上。如果你需要不同的构造函数,那么你应该覆盖/隐藏它。

标签: .net vb.net inheritance


【解决方案1】:

我怀疑真正的原因是双重的:

首先,no 静态 (Shared) 成员在 VB#(或 C#)中被继承。虽然这与大多数 OO 语言所做的一致,但这不是必要的设计。可以想象,它的实施方式可能有所不同。

其次,限制可以构造子对象的构造函数集通常是有意义的。特别是,由于子类通常具有需要初始化的其他成员,因此调用父类构造函数会使子类处于未初始化状态。想象一下构造函数可以被继承并告诉我下面的代码应该做什么:

Class Base
    Public Sub New()
    End Sub
End Class

Class Derived : Inherits Base
    Public Property X() As Integer

    Public Sub New(ByVal value As Integer)
        X = value
    End Sub
End Class

' …

Dim foo As New Derived()
Console.WriteLine(foo.X) ' = ???

鉴于此,禁止构造函数的继承是很有意义的。

【讨论】:

【解决方案2】:

继承(或者,准确地说,一个子类型关系)保证如果ST 的子类型,您可以在任何时候使用S 类型的对象类型 T 是必需的。

构造函数永远不能在一个对象上执行——它们被执行以创建一个对象。它们的特别之处在于:

myS.SomeMethodOfT()    ' works
myS.New()              ' doesn't work -- constructors are special.

换句话说,构造函数可以被视为返回特定类型对象的静态(Visual Basic 中为Shared)方法(并且某些语言实际上以这种方式实现它):

Dim myS = New S()      ' can be seen as syntactic sugar for 
                       ' something like myS = S.CreateNew()

【讨论】:

  • +1 但我想提一下,这在概念上是不必要的。我们可以(并且某些语言可以)扩展可继承的接口契约以包含静态方法(例如对象创建)。
  • 好的,但是 S 构造函数如何初始化 T 的私有字段呢?您必须以某种方式调用 T 中知道如何填充它们的方法,例如调用其中一个构造函数。 OP 想知道为什么它没有自动连接。
  • @KonradRudolph:很好,谢谢。我主要想指出为什么不继承构造函数不会“破坏继承”。
  • @Rup:没有。 S 的构造函数隐式或显式调用 T 的构造函数,由它负责。
  • 当然 - 我以为你说那是不可能的。我不知道 VB.NET 语法,所以可能我理解错了。
【解决方案3】:

在构造函数中,你应该只为那个类构造元素,而不是它的基类。通过调用基类的构造函数,这些元素将被构造出来。

【讨论】:

  • 我不明白这与这个问题有什么关系。需要详细说明吗?
  • 因为每个构造函数只构造自己的元素,并且总是应该调用基构造函数。而且它们大多有不同的参数(基本构造函数参数大多等于或小于派生构造函数)。
【解决方案4】:

除了已经给出的答案之外,看看对象创建的语义也很有趣。

如果类 B 继承自类 A,那么类 B 的所有对象都有两个组成部分:A 的部分(被继承)和 B 的部分(可能覆盖A)。

因此,您可以将对象视为所有祖先类的部分的总和(加上其自身类的部分)。

现在考虑创建对象:如果创建了 B 类的对象,不仅必须创建 B 部分,还必须创建 A 部分。换句话说,如果 B 的构造函数被调用,A 的构造函数也必须被调用(这种情况总是,即使你没有在 C# 中显式调用 base() 或 @987654322 @ 在 VB 中)。

如果 B 从 A 继承其构造函数,那么它可以覆盖这样的构造函数。这可能会导致 A 没有剩余的构造函数来构建自己的部分(因为所有构造函数都被覆盖),这使得 A 部分的对象创建变得不可能。

不继承构造函数不会破坏继承,它使继承成为可能!

【讨论】:

  • 问题不在于对基类构造函数的链式调用,而是相反:如果派生类继承了基类构造函数,调用该构造函数会使派生类中的新内容未初始化.如果可以定义派生类构造函数derived(int foo, ...) : base(foo, ...) 并让它自动生成与所有基类构造函数对应的派生类构造函数,并将int 作为第一个参数,那将很有帮助;然而,这样的行为不会是构造函数的“继承”,而是别的东西。
【解决方案5】:

为什么构造函数不能被继承的各种论据是错误的。 pascal 和 c 都是真正的面向对象语言,都允许继承构造函数。

上面引用的例子……

Class Base
    Public Sub New()
    End Sub
End Class

Class Derived : Inherits Base
    Public Property X() As Integer
    Public Sub New(ByVal value As Integer)
        X = value
    End Sub
End Class

'…… Dim foo As New Derived()

Console.WriteLine(foo.X) ' = ???

答案是...foo.x 未初始化。但是使用未初始化的变量不是语言的错……这是程序员的错。

考虑另一个例子...

Class Base
    Public Property X As Integer
    Public Sub New(ByVal value As Integer)
        X = value
    End Sub
End Class

Class Derived : Inherits Base
End Class

'这行得通... Dim o 作为 Base = New Base(5) '这没有。它可以在 pascal 或 c 中工作......但在 vb(或可能是 c#)中不起作用

Dim o as Derived = New Derived(5)

重点是继承的类不应该重写构造函数,除非它改变了它的签名。现实情况是,这是微软拿走一个有价值的工具的一个例子,因为太多的程序员无法正确使用该工具。

【讨论】:

    猜你喜欢
    • 2020-02-28
    • 2013-08-27
    • 1970-01-01
    • 2012-04-16
    • 2015-10-18
    • 2013-08-11
    相关资源
    最近更新 更多