VB.NET 中的“阴影”与“覆盖”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/463209/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
'Shadows' vs. 'Overrides' in VB.NET
提问by Jeff
采纳答案by Jim Petkus
I wouldn't consider Shadows to really be an OOP concept. Overrides indicates that you are providing new or additional functionality for a method/property etc that was declared in an ancestor class. Shadows really tricks the compiler into thinking that the parent method/property etc does not even exist.
我不会认为 Shadows 真的是一个面向对象的概念。Overrides 表示您正在为在祖先类中声明的方法/属性等提供新的或附加的功能。阴影真的让编译器认为父方法/属性等甚至不存在。
I have no use for Shadows. Stick to Overrides. These types of helpful little "features" that VB has provided for years always end up causing you grief at some point.
我对阴影没有用。坚持覆盖。VB 多年来提供的这些有用的小“功能”总是在某些时候让您感到悲伤。
回答by Nick
Overridesis the more normal qualifier. If the child class redefines a base class function in this way, then regardless of how a child object is referenced (using either a base class or a child class reference) it is the child function that is called.
Overrides是更正常的限定符。如果子类以这种方式重新定义基类函数,那么无论子对象如何被引用(使用基类或子类引用),都会调用子函数。
On the other hand, if the child class function Shadowsthe base class function, then a child object accessed via a base class reference will use that base class function, despite being a child object.
The child function definition is only used if the child object is accessed using a matching child reference.
另一方面,如果子类函数隐藏基类函数,则通过基类引用访问的子对象将使用该基类函数,尽管它是子对象。
仅当使用匹配的子引用访问子对象时才使用子函数定义。
回答by dwidel
Shadowing probably doesn't do what you think it does.
阴影可能不会像你认为的那样做。
Consider the following classes:
考虑以下类:
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
Now I use them:
现在我使用它们:
Dim oA As A
Dim oB As New B
oA = oB
You probably think oA and oB are the same right?
你可能认为 oA 和 oB 是一样的吧?
Nope.
不。
oA.fx = 0 while oB.fx = 1
oA.fx = 0 而 oB.fx = 1
Imho this is very dangerous behavior and it's barely mentioned in the docs.
恕我直言,这是非常危险的行为,文档中几乎没有提到。
If you had used override they would be the same.
如果您使用了覆盖,它们将是相同的。
So while there are legitimate uses for shadows, chances are whatever you're doing is not one of them and it should be avoided.
因此,虽然阴影有合法用途,但很可能您正在做的事情不是其中之一,应该避免使用。
回答by user50612
Overrides - Extending or creating alternate functionality for a method.
覆盖 - 为方法扩展或创建替代功能。
Example: Add or extended the functionality of the Paint event of a window.
示例:添加或扩展窗口的 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
Shadows - Redefines an inherited method and forces its use for all classes instanced with that type. In other words the method is not overloaded but redefined and the base class methods are not available, thus forcing the use of the function declared in the class. Shadows preserves or retains the definition of the method such that it is not destroyed if the base class methods are modified.
Shadows - 重新定义继承的方法并强制将其用于所有使用该类型实例化的类。换句话说,该方法没有重载而是重新定义,并且基类方法不可用,从而强制使用类中声明的函数。Shadows 保留或保留方法的定义,以便在修改基类方法时不会破坏它。
Example: Force all "B" classes to use it's oddball Add definition such that if A class Add methods are modified it won't affect B's add. (Hides all base class "Add" methods. Won't be able to call A.Add(x, y, z) from an instance of B.)
示例:强制所有“B”类使用它奇怪的 Add 定义,这样如果 A 类的 Add 方法被修改,它就不会影响 B 的 add。(隐藏所有基类“Add”方法。将无法从 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
回答by the_lotus
Sometime a small example really helps understand the difference in a technical way.
有时,一个小例子确实有助于从技术上理解差异。
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
回答by supercat
The "shadows" keyword essentially says "If whoever is accessing this object knows it to be of this type or one of its descendents, use this member; otherwise use the base one." The simplest example of this might be a base class ThingFactory, which includes a "MakeNew" method which returns a Thing, and a class CarFactory, derived from ThingFactory, whose "MakeNew" method always returns a Thing that will be of derived type Car. If a routine knows that a ThingFactory it holds happens to, more particularly, be a CarFactory, then it will use a shadowed CarFactory.MakeNew (if one exists), which can specify the return type as Car. If a routine doesn't know that its ThingFactory is actually a CarFactory, it will use a non-shadowed MakeNew (which should call an internal protected overridable MakeDerivedThing method).
“shadows”关键字本质上是说“如果访问此对象的任何人都知道它属于这种类型或其后代之一,则使用此成员;否则使用基本成员。” 最简单的例子可能是一个基类 ThingFactory,它包括一个返回 Thing 的“MakeNew”方法和一个从 ThingFactory 派生的类 CarFactory,它的“MakeNew”方法总是返回一个派生类型 Car 的 Thing。如果例程知道它所持有的 ThingFactory 恰好是 CarFactory,那么它将使用阴影的 CarFactory.MakeNew(如果存在),它可以将返回类型指定为 Car。如果一个例程不知道它的 ThingFactory 实际上是一个 CarFactory,
Incidentally, another good use of shadows is to prevent derived classes from accessing Protected methods which will no longer work. There's no way of simply hiding a member from derived classes other than assigning a new one, but one can prevent derived classes from doing anything with a protected member by declaring a new protected empty class with that name. For example, if calling MemberwiseClone on an object would break it, one can declare:
顺便说一句,阴影的另一个很好的用途是防止派生类访问不再有效的受保护方法。除了分配一个新成员之外,没有办法简单地从派生类中隐藏成员,但是可以通过声明具有该名称的新受保护空类来防止派生类对受保护成员执行任何操作。例如,如果在对象上调用 MemberwiseClone 会破坏它,则可以声明:
Protected Shadows Class MemberwiseClone End Class请注意,这并不违反像 Liskov 替换原则这样的 OOP 原则,因为这仅适用于派生类可能用于代替基类对象的情况。如果 Foo 和 Bar 继承自 Boz,则可以合法地在 Foo 或 Bar 中传递接受 Boz 参数的方法。另一方面,Foo 类型的对象会知道它的基类对象是 Boz 类型的。它永远不会是其他任何东西(例如,它保证不是酒吧)。
回答by supercat
An example of shadowing: Let's assume that you want to use a function in a third-party component, but the function is protected. You can bypass this constraint with simple inheritance and exposing a shadowed function which basically calls its base function:
阴影的一个例子:假设您想在第三方组件中使用一个函数,但该函数是受保护的。您可以通过简单的继承来绕过此约束并公开一个基本上调用其基函数的阴影函数:
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
回答by ebol2000
I think there are really two scenarios that people are taking on here and both are legitimate. You could really break them down into the base class designer and the developer years later who is implementing the subclass who cannot modify the base class. So yes, the best thing to do is override if you have that luxury. This is the clean OOD approach.
我认为人们在这里真的有两种情况,而且两种情况都是合法的。您真的可以将它们分解为基类设计者和多年后实现无法修改基类的子类的开发人员。所以是的,如果你有这种奢侈,最好的办法就是覆盖。这是干净的OOD方法。
On the other hand you may have something like example given above where you are on the other end of this equation having to implement a sub class and you cannot change the fact that the method you need to override is not marked overridable. Take for example
另一方面,您可能有类似上面给出的示例的内容,您在此等式的另一端必须实现子类,并且您无法更改需要覆盖的方法未标记为可覆盖的事实。以
Public Shadows Function Focus() As Boolean
txtSearch.Focus()
Return MyBase.Focus()
End Function
In this case I'm inheriting my class from the Winform control class which unfortunately isn't marked as overridable. At this point I'm faced with just making the code "pure" or making it easier to understand. The client of this control simply wants to call control.Focus() and probably doesn't care. I could have named this method FocusSearchText() or Focus2, etc but I believe the above is much more simple for the client code. It's true that if the client then casts this control as the base class and calls Focus my code won't excute. But that is fairly remote.
在这种情况下,我从 Winform 控件类继承我的类,不幸的是它没有被标记为可覆盖。在这一点上,我面临的只是使代码“纯”或使其更易于理解。此控件的客户端只是想调用 control.Focus() 并且可能并不关心。我可以将这个方法命名为 FocusSearchText() 或 Focus2 等,但我相信以上对于客户端代码来说要简单得多。确实,如果客户端然后将此控件转换为基类并调用 Focus 我的代码将不会执行。但那是相当遥远的。
In the end it comes down to a judgement call, and one you'll have to make.
最后归结为一个判断,你必须做出判断。
回答by Jerry
Shadow allows you to do certain things that cannot be done with overrides.
Shadow 允许您执行某些覆盖无法完成的操作。
In my own case: I have several tables classes with generic functionality; but for whom the collections themselves are of different types.
在我自己的情况下:我有几个具有通用功能的表类;但对于他们而言,这些藏品本身就是不同类型的。
Public Class GenericTable
Protected Friend Overridable Property Contents As System.Collections.Generic.List(Of GenericItem)
... do stuff ...
End Class
Then I have specific isntances:
然后我有具体的情况:
Public Class WidgetTable
Inherits GenericTable
Protected Friend Shadows Property Contents As System.Collections.Generic.List(Of Widget)
... stuff is inhereted ...
End Class
I could not override because the the type is changed.
我无法覆盖,因为类型已更改。
回答by Lucio Menci
I found another difference. See this:
我发现了另一个不同之处。看到这个:
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
If you are using Overrides (where there is $$$) THERE IS NO WAY to use Func on Base class either if the definition of the instance is Derived, and if the definition is base but the instance is of the Derived type.
如果您正在使用 Overrides(其中有 $$$),则如果实例的定义是派生的,并且定义是基类但实例是派生的类型,则无法在基类上使用 Func。
If you are using Shadows, the only way you can see the Func into the derived class, is to define the instance as Derived, and without passing to a method of base class (X.Test returns Standard). I think this is the main one: If I use Shadows, the method won't overload the base method inside base methods.
如果您使用的是Shadows,那么您可以在派生类中看到Func 的唯一方法是将实例定义为Derived,并且不传递给基类的方法(X.Test 返回Standard)。我认为这是主要的:如果我使用阴影,该方法不会重载基方法中的基方法。
This is the OOP approach of Overloads. If I derive a class and IN NO CASE I want that a method would be called, I have to use Overloads. For instances of my objects, there is no way to return "Standard" (Except using reflections, I think). I think intellisense make a bit of confusion. If I highlight Y.Func, there will be highlighted the Func into base class, but is executed the Func into derived class.
这是重载的 OOP 方法。如果我派生一个类并且在任何情况下我都不想调用一个方法,我必须使用重载。对于我的对象实例,无法返回“标准”(我认为除了使用反射)。我认为智能感知有点混乱。如果我突出显示Y.Func,则会突出显示Func into base class,但会在派生类中执行Func。
With Shadows, the new method is reachable only directly. As such as Overloads, but hiding the overloads of the base class (I think it's an error returned before the compilation, because you can call it using a cast, as such as implicit done using a overload).
使用 Shadows,新方法只能直接访问。比如Overloads,但是隐藏了基类的重载(我认为这是在编译之前返回的错误,因为你可以使用强制转换来调用它,比如使用重载隐式完成)。
回答by CMH
This is a recent MSDN link: Differences between shadowing and overriding
这是最近的 MSDN 链接: Differences between shadowing and overriding
Shadowing protects against a subsequent base-class modification that introduces a member you have already defined in your derived class. You normally use shadowing in the following cases:
遮蔽可防止随后的基类修改引入您已在派生类中定义的成员。通常在以下情况下使用阴影:
** You anticipate that your base class might be modified to define an element using the same name as yours.*
** 您预计您的基类可能会被修改以使用与您的名称相同的名称来定义元素。*
** You want the freedom of changing the element type or calling sequence.*
** 您想要自由更改元素类型或调用顺序。*
(I'm yet to investigate usage with respect to scope and types)
(我还没有调查关于范围和类型的用法)

