两个关键字Shadows和Overrides有什么意义?他们做了什么以及哪个环境是一个或另一个更好?
覆盖是更常规的限定符.如果子类以这种方式重新定义基类函数,那么无论如何引用子对象(使用基类或子类引用),它都是被调用的子函数.
另一方面,如果子类函数Shadows基类函数,则通过基类引用访问的子对象将使用该基类函数,尽管它是子对象.
仅当使用匹配的子引用访问子对象时,才使用子函数定义.
暗影可能不会像你想象的那样做.
考虑以下类:
Public MustInherit Class A Public Function fX() As Integer Return 0 End Function End Class Public Class B Inherits A Public Shadows Function fX() As Integer Return 1 End Function End Class
现在我用它们:
Dim oA As A Dim oB As New B oA = oB
您可能认为oA和oB是一样的吗?
不.
oA.fx = 0而oB.fx = 1
Imho这是非常危险的行为,在文档中几乎没有提到.
如果您使用了覆盖,它们将是相同的.
因此,虽然阴影有合法用途,但是你所做的一切都不是其中之一,应该避免.
覆盖 - 扩展或创建方法的备用功能.
示例:添加或扩展窗口的Paint事件的功能.
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs) MyBase.OnPaint(e) ' retain the base class functionality 'add code for extended functionality here End Sub
阴影 - 重新定义继承的方法并强制其用于使用该类型实例化的所有类.换句话说,该方法没有重载但重新定义,并且基类方法不可用,因此强制使用在类中声明的函数.阴影保留或保留方法的定义,以便在修改基类方法时不会销毁它.
示例:强制所有"B"类使用它的古怪添加定义,如果修改了A类Add方法,它将不会影响B的添加.(隐藏所有基类"添加"方法.将无法从B的实例调用A.Add(x,y,z).)
Public Class A Public Function Add(ByVal x As Integer, ByVal y As Integer) As Integer Return x + y End Function Public Function Add(ByVal x As Integer, ByVal y As Integer, ByVal z As Integer) As Integer Return x + y + z End Function End Class Public Class B Inherits A Public Shadows Function Add(ByVal x As Integer, ByVal y As Integer) As Integer Return x - y End Function End Class
有时,一个小例子确实有助于理解技术方面的差异.
Sub Main() Dim o As New ChildClass Console.WriteLine(o.GetValOverride()) ' Prints 2 Console.WriteLine(o.GetValShadow()) ' Prints 2 Console.WriteLine(CType(o, ParentClass).GetValOverride()) ' Prints 2 Console.WriteLine(CType(o, ParentClass).GetValShadow()) ' Prints 1 Console.ReadLine() End Sub Class ParentClass Public Overridable Function GetValOverride() As String Return "1" End Function Public Function GetValShadow() As String Return "1" End Function End Class Class ChildClass Inherits ParentClass Public Overrides Function GetValOverride() As String Return "2" End Function Public Shadows Function GetValShadow() As String Return "2" End Function End Class
阴影示例:假设您要在第三方组件中使用函数,但该函数受到保护.您可以通过简单继承绕过此约束并公开一个基本上调用其基本函数的阴影函数:
Public Class Base Protected Sub Configure() .... End Sub End Class Public Class Inherited Inherits Base Public Shadows Sub Configure() MyBase.Configure() End Sub End Class
"shadows"关键字基本上表示"如果访问此对象的人知道它属于此类型或其后代之一,请使用此成员;否则使用基本成员." 最简单的例子可能是基类ThingFactory,它包含一个返回Thing的"MakeNew"方法,以及一个派生自ThingFactory的CarFactory类,其"MakeNew"方法总是返回一个派生类型为Car的Thing.如果例程知道它所持有的ThingFactory,更具体地说是CarFactory,那么它将使用阴影CarFactory.MakeNew(如果存在),它可以将返回类型指定为Car.如果例程不知道它的ThingFactory实际上是CarFactory,它将使用非阴影的MakeNew(它应该调用内部受保护的可覆盖的MakeDerivedThing方法).
顺便说一句,阴影的另一个好用途是防止派生类访问不再有效的Protected方法.除了分配新成员之外,没有办法简单地从派生类隐藏成员,但是可以通过声明具有该名称的新受保护空类来阻止派生类对受保护成员执行任何操作.例如,如果在对象上调用MemberwiseClone会破坏它,可以声明:
Protected Shadows Class MemberwiseClone End Class请注意,这并不违反Liskov替换原则之类的OOP原则,因为这仅适用于可能使用派生类代替基类对象的情况.如果Foo和Bar继承自Boz,则接受Boz参数的方法可以合法地在Foo或Bar中传递.另一方面,类型为Foo的对象将知道其基类对象是Boz类型.它永远不会是其他任何东西(例如它保证不是一个酒吧).