作为后续问题,请Base Class Only Methods
父方法由其后代继承。
为什么构造函数(例如New())不是? 这对我来说似乎打破了继承。
是否有某个属性将其标记为特殊? (如果是这样的话是什么?)
可以这样解释发生了什么。
答案 0 :(得分:4)
我怀疑真正的原因是双重的:
首先, 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) ' = ???
鉴于此,禁止构造函数的继承是很有意义的。
答案 1 :(得分:2)
继承(或者,确切地说,子类型关系)保证如果S
是T
的子类型,则可以使用{{1}类型的对象每当需要S
类型的对象时。
构造函数永远不能在对象上执行 - 它们被执行到创建对象。它们很特别:
T
换句话说,构造函数可以被视为静态(Visual Basic中的myS.SomeMethodOfT() ' works
myS.New() ' doesn't work -- constructors are special.
)方法返回特定类型的对象(并且某些语言实际上以这种方式实现):
Shared
答案 2 :(得分:1)
在构造函数中,您应该只构造该类的元素,而不是它的基类。通过调用基类的构造函数,将构造这些元素。
答案 3 :(得分:0)
除了已经给出的答案之外,还可以看一下对象创建的语义。
如果B类继承自A类,那么B类的所有对象都有两个组成部分:A的部分(继承)和B的部分(可能覆盖部分的部分) A)。
所以你可以把一个对象想象成所有祖先类的部分之和(加上它自己类的部分)。
现在考虑创建对象:如果创建了B类的对象,则不仅必须创建B部分,还要创建A部分。换句话说,如果调用B的构造函数,也必须调用A的构造函数(即使你没有在C#中显式调用base()
,这也是总是的情况。 VB中的MyBase.New()
。
如果B从A继承其构造函数,那么它可以覆盖这样的构造函数。这可能导致A没有构造自己的部分的构造函数(因为所有构造函数都被覆盖),这使得A部分的对象创建成为不可能。
不继承构造函数不会破坏继承,它使它成为可能!
答案 4 :(得分:0)
为什么构造函数不能被继承的各种参数都是错误的。 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()
答案是...... 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 as Base = New Base(5) '这不是。它可以用于pascal或c ......但不能用于vb(或者可能是c#)
重点是继承的类不应该重写构造函数,除非它正在更改它的签名。现实情况是,这是微软拿走有价值工具的一个例子,因为太多的程序员无法正确使用该工具。