VB.NET中的"阴影"与"覆盖"

Jef*_*eff 64 .net vb.net oop overriding shadows

两个关键字ShadowsOverrides有什么意义?他们做了什么以及哪个环境是一个或另一个更好?

Nic*_*ick 87

覆盖是更常规的限定符.如果子类以这种方式重新定义基类函数,那么无论如何引用子对象(使用基类或子类引用),它都是被调用的子函数.

另一方面,如果子类函数Shadows基类函数,则通过基类引用访问的子对象将使用该基类函数,尽管它是子对象.
仅当使用匹配的子引用访问子对象时,才使用子函数定义.


小智 20

暗影可能不会像你想象的那样做.

考虑以下类:

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
Run Code Online (Sandbox Code Playgroud)

现在我用它们:

Dim oA As A
Dim oB As New B
oA = oB
Run Code Online (Sandbox Code Playgroud)

您可能认为oA和oB是一样的吗?

不.

oA.fx = 0而oB.fx = 1

Imho这是非常危险的行为,在文档中几乎没有提到.

如果您使用了覆盖,它们将是相同的.

因此,虽然阴影有合法用途,但是你所做的一切都不是其中之一,应该避免.


use*_*612 15

覆盖 - 扩展或创建方法的备用功能.

示例:添加或扩展窗口的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
Run Code Online (Sandbox Code Playgroud)

阴影 - 重新定义继承的方法并强制其用于使用该类型实例化的所有类.换句话说,该方法没有重载但重新定义,并且基类方法不可用,因此强制使用在类中声明的函数.阴影保留或保留方法的定义,以便在修改基类方法时不会销毁它.

示例:强制所有"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
Run Code Online (Sandbox Code Playgroud)

  • 幸运的是,这个线程是关于他们做什么以及他们使用什么上下文. (3认同)

the*_*tus 10

有时,一个小例子确实有助于理解技术方面的差异.

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
Run Code Online (Sandbox Code Playgroud)


小智 6

阴影示例:假设您要在第三方组件中使用函数,但该函数受到保护.您可以通过简单继承绕过此约束并公开一个基本上调用其基本函数的阴影函数:

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
Run Code Online (Sandbox Code Playgroud)


sup*_*cat 6

"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类型.它永远不会是其他任何东西(例如它保证不是一个酒吧).


Jim*_*kus -14

我不认为 Shadows 真的是一个 OOP 概念。覆盖表示您正在为祖先类中声明的方法/属性等提供新的或附加的功能。阴影确实欺骗编译器认为父方法/属性等甚至不存在。

我对影子没有任何用处。坚持覆盖。VB 多年来提供的这些有用的小“功能”最终总会在某些时候给您带来悲伤。

  • -1。阴影是一个独特且有用的概念。它隐藏所有具有相同名称的基类方法并强制使用已声明的方法。Overrides 不会隐藏所有基类方法。 (28认同)
  • -1 C# 等效项是“new”,因此 private new string Test() {...} 执行相同的操作。不仅仅是 vb.net 的“问题” (25认同)
  • 你应该得到-2,首先是因为不尊重非常有用的 Shadows 词,然后是因为不知道你引以为豪的语言的基本关键字,“侮辱”其他语言 (7认同)
  • 一旦您隐藏了继承的方法,该类就不再被视为其祖先的真正后代。恕我直言,这不是真正的 OOP,我对导致这条道路的应用程序设计提出质疑。在某些情况下,这可能是必要的,但通常没有必要。 (4认同)
  • 我不确定是否要否决这个答案,因为其他否决者的所有更正都非常有用,我不希望回答者将答案标记为已删除。 (4认同)
  • 然而,我同意,问题是关于它们做什么以及它们在什么上下文中使用的问题 - 这不是关于是否有人认为它们是 OOP 概念。 (2认同)
  • -1; 正如其他人所说,这并不能真正回答问题。 (2认同)
  • -1 表示“阴影”是一个糟糕的功能,只是因为您不理解它的含义。 (2认同)