';阴影';与';覆盖';在VB.NET中

';阴影';与';覆盖';在VB.NET中,.net,vb.net,oop,overriding,shadows,.net,Vb.net,Oop,Overriding,Shadows,这两个关键词的意义是什么?他们所做的和哪一个上下文是一个或另一个更可取的? < P>我不认为阴影真的是一个面向对象的概念。重写表示您正在为祖先类中声明的方法/属性等提供新的或附加的功能。阴影确实欺骗了编译器,使其认为父方法/属性等甚至不存在 我不喜欢阴影。坚持覆盖。VB多年来提供的这些有用的小“功能”总会在某个时候让你感到悲伤。我同意Jim的观点。我也从来没有找到阴影的合法用途。通常,如果我看到它,我会假设代码的子部分需要重构一点 我想它就在那里,这样你就可以从一个你不能控制源代码的程序集中隐藏

这两个关键词的意义是什么?他们所做的和哪一个上下文是一个或另一个更可取的?

< P>我不认为阴影真的是一个面向对象的概念。重写表示您正在为祖先类中声明的方法/属性等提供新的或附加的功能。阴影确实欺骗了编译器,使其认为父方法/属性等甚至不存在


我不喜欢阴影。坚持覆盖。VB多年来提供的这些有用的小“功能”总会在某个时候让你感到悲伤。

我同意Jim的观点。我也从来没有找到阴影的合法用途。通常,如果我看到它,我会假设代码的子部分需要重构一点


我想它就在那里,这样你就可以从一个你不能控制源代码的程序集中隐藏一个方法。在这种情况下,重构父类是不可能的。

重写-扩展或创建方法的替代功能

示例:添加或扩展窗口绘制事件的功能


    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”类使用其古怪的Add定义,这样,如果修改了类Add方法,则不会影响B的Add。(隐藏所有基类“Add”方法。将无法从B的实例调用A.Add(x,y,z)


覆盖是更普通的限定符。如果子类以这种方式重新定义基类函数,则无论如何引用子对象(使用基类或子类引用),调用的都是子函数

另一方面,如果子类函数阴影基类函数,则通过基类引用访问的子对象将使用该基类函数,尽管它是子对象。

仅当使用匹配的子引用访问子对象时,才使用子函数定义。

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

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

这是最近的MSDN链接:

阴影可以防止后续基类修改引入已在派生类中定义的成员。 通常在以下情况下使用阴影:

**您预期基类可能会被修改,以使用与您相同的名称定义元素*

**您希望可以自由更改元素类型或调用顺序*


(我还没有调查范围和类型方面的用法)

我想使用
System.Web.HttpContext.Current.Response
而不是
Response.redirect
,并且需要方便地编码为
Response.redirect
。我定义了一个名为
Response
的只读属性来在基类中隐藏原始属性。我无法使用重写,因为此属性不可重写。非常方便:)

阴影可能不会像你想象的那样

考虑以下类别:

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

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

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

因此,虽然阴影有合法的用途,但很可能你所做的任何事情都不是其中之一,应该避免。“阴影”关键字实质上是说“如果访问此对象的人知道它属于此类型或其后代,请使用此成员;否则,请使用基本成员。”最简单的例子可能是基类ThingFactory,它包括一个“MakeNew”方法(返回一个对象)和一个从ThingFactory派生的类CarFactory,后者的“MakeNew”方法总是返回一个派生类型为Car的对象。如果例程知道它持有的ThingFactory恰好是一个CarFactory,那么它将使用一个阴影CarFactory.MakeNew(如果存在),它可以将返回类型指定为Car。如果一个例程不知道它的ThingFactory实际上是一个CarFactory,它将使用一个非阴影MakeNew(它应该调用一个内部保护的可重写MakeDerivedThing方法)

顺便提一下,阴影的另一个很好的用途是防止派生类访问不再工作的受保护方法。除了分配一个新的成员外,无法简单地从派生类中隐藏成员,但是可以通过声明一个具有该名称的新的受保护空类来防止派生类对受保护的成员执行任何操作。例如,如果对对象调用MemberwiseClone会破坏它,可以声明: Protected Shadows Class MemberwiseClone End Class 受保护的阴影类MemberwiseClone 末级
请注意,这并不违反像Liskov替换原则这样的OOP原则,因为这只适用于可能使用派生类代替基类对象的情况。如果Foo和Bar继承自Boz,则接受Boz参数的方法可以合法地在Foo或Bar中传递。另一方面,Foo类型的对象将知道其基类对象是Boz类型。它将永远不会是其他任何东西(例如,它保证不会是酒吧)。

我认为这里确实有两种情况,人们正在接受,而且两种情况都是错误的 Protected Shadows Class MemberwiseClone End Class
Public Shadows Function Focus() As Boolean
    txtSearch.Focus()
    Return MyBase.Focus()
End Function
Public Class GenericTable
Protected Friend Overridable Property Contents As System.Collections.Generic.List(Of GenericItem)
    ... do stuff ...
End Class
Public Class WidgetTable
Inherits GenericTable
Protected Friend Shadows Property Contents As System.Collections.Generic.List(Of Widget)
    ... stuff is inhereted ...
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
Sub Main()
    Dim X As New Derived
    Dim Y As Base = New Derived
    Console.WriteLine("X:" & X.Test())
    Console.WriteLine("Y:" & Y.Test())
    Console.WriteLine("X:" & CType(X, Base).Test)
    Console.WriteLine("X:" & X.Func())
    Console.WriteLine("Y:" & Y.Func())
    Console.WriteLine("X:" & CType(X, Base).Func)
    Console.ReadKey()
End Sub
Public Class Base
    Public Overridable Function Func() As String
        Return "Standard"
    End Function
    Function Test() As String
        Return Me.Func()
    End Function
End Class
Public Class Derived
    Inherits Base
    Public $$$ Function Func() As String
        Return "Passed By Class1" & " - " & MyBase.Func
    End Function
End Class
Module Module1

    Sub Main()
        Dim object1 As Parent = New Child()
        Console.WriteLine("object1, reference type Parent and object type Child")
        object1.TryMe1()
        object1.TryMe2()
        object1.TryMe3()

        Console.WriteLine("")
        Console.WriteLine("")
        Console.WriteLine("object2, reference type Child and object type Child")
        Dim object2 As Child = New Child()

        object2.TryMe1()
        object2.TryMe2()
        object2.TryMe3()

        Console.ReadLine()
    End Sub

End Module

Public Class Parent

    Public Sub TryMe1()
        Console.WriteLine("Testing Shadow: Parent.WriteMe1")
    End Sub

    Public Overridable Sub TryMe2()
        Console.WriteLine("Testing override: Parent.WriteMe2")
    End Sub

    Public Sub TryMe3()
        Console.WriteLine("Testing Shadow without explicitly writing shadow modifier: Parent.WriteMe3")
    End Sub
End Class

Public Class Child
    Inherits Parent

    Public Shadows Sub TryMe1()
        Console.WriteLine("Testing Shadow: Child.WriteMe1")
    End Sub

    Public Overrides Sub TryMe2()
        Console.WriteLine("Testing override: Child.WriteMe2")
    End Sub

    Public Sub TryMe3()
    Console.WriteLine("Testing Shadow without explicitly writing shadow modifier: Child.WriteMe3")
    End Sub
End Class


'Output:
'object1, reference type Parent and object type Child
'Testing Shadow: Parent.WriteMe1
'Testing override: Child.WriteMe2
'Testing Shadow without explicitly writing shadow modifier: Parent.WriteMe3


'object2, reference type Child and object type Child
'Testing Shadow: Child.WriteMe1
'Testing override: Child.WriteMe2
'Testing Shadow without explicitly writing shadow modifier: Child.WriteMe3