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
我无法覆盖,因为类型已更改。
Shadow allows you to do certain things that cannot be done with overrides.
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.
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
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.
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.
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.
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).
例如围绕组合框。 通过隐藏 AutoCompleteSource,您可以防止将其设置为特殊类型组合框的非法值,即使它被转换为普通组合框也是如此。 或者在阴影属性中使用 mybase.AutoCompleteSource = value 之前进行一些预处理。
Shadows can be very useful if you are writing a wrapper around an existing control.
For instance around a combobox. By shadowing the AutoCompleteSource you can prevent it to be set to a illegitimate value for your special kind of combobox even when it's cast to a normal combobox. Or do some pre-proccessing before you use mybase.AutoCompleteSource = value in the shadowing property.
VB use more advanced OOP concepts than C#, for use overriding in derived class in C# you MUST mark method as "vitrual", Shadow allow you make overload without this.
The use of Shadows is rare but true. Moreover you cannot override a shared (static) method. So you must shadow a shared method if you want to "override" it.
I agree with Jim. I've never found a legitimate use for Shadows, either. Usually if I see it, I assume that sub-section of the code needs to be refactored a bit.
I suppose it is there so that you can shadow a method from an assembly in which you do not have control over the source code. In that case, refactoring the parent class would be impossible.
I wanted to use System.Web.HttpContext.Current.Response instead of Response.redirect, and needed the convenience to code as Response.redirect. I defined a readonly property named Response to shadow the original in a base class. I couldn't use overrides, since this property is not overridable. Very convenient:)
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.
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.
Overrides is 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.
On the other hand, if the child class function Shadows the 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.
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 while oB.fx = 1
恕我直言,这是非常危险的行为,文档中几乎没有提到。
如果您使用了覆盖,它们将是相同的。
因此,虽然阴影有合法的用途,但您所做的很可能不是其中之一,应该避免。
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?
Nope.
oA.fx = 0 while 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.
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 定义,这样如果 A 类的 Add 方法被修改,则不会影响 B 的添加。 (隐藏所有基类“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
Overrides - Extending or creating alternate functionality for a method.
Example: Add or extended the functionality of the Paint event of a window.
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.
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.)
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
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
Note that this does not violate OOP principles like the Liskov Substitution Principle, since that only applies in cases where a derived class might be used in place of a base-class object. If Foo and Bar inherits from Boz, a method which accepts a Boz parameter may legitimately be passed in a Foo or Bar instead. On the other hand, an object of type Foo will know that its base-class object is of type Boz. It will never be anything else (e.g. it's guaranteed not to be a Bar).
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).
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:
Protected Shadows Class MemberwiseClone
End Class
Note that this does not violate OOP principles like the Liskov Substitution Principle, since that only applies in cases where a derived class might be used in place of a base-class object. If Foo and Bar inherits from Boz, a method which accepts a Boz parameter may legitimately be passed in a Foo or Bar instead. On the other hand, an object of type Foo will know that its base-class object is of type Boz. It will never be anything else (e.g. it's guaranteed not to be a Bar).
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
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
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.
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.
In the end it comes down to a judgement call, and one you'll have to make.
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)
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
您可以复制粘贴此内容并自行尝试。 正如您所看到的,阴影是默认行为,并且当您没有显式编写阴影修饰符时,Visual Studio 会在阴影发生时向您发出警告。
注意:对我来说,我从未使用过对子对象的基类引用。 对于这种情况,我总是使用接口。
Well here is the answer by Code.
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
You can copy paste this and try it yourself. As you can see the shadowing is the default behavior, and Visual Studio does warn you when shadowing is going on without you explicitly writing the shadow modifier.
Note: For me, I have never used a Base class reference to a child object. For such cases I always use Interfaces.
发布评论
评论(17)
Shadow 允许您执行某些无法通过覆盖完成的操作。
就我自己而言:我有几个具有通用功能的表类; 但对于谁来说,藏品本身有不同的类型。
然后我有具体的情况:
我无法覆盖,因为类型已更改。
Shadow allows you to do certain things that cannot be done with overrides.
In my own case: I have several tables classes with generic functionality; but for whom the collections themselves are of different types.
Then I have specific isntances:
I could not override because the the type is changed.
我发现了另一个不同之处。 请参阅:
如果您正在使用覆盖(其中有 $$$),则如果实例的定义是派生的,并且定义是基类但实例是派生类型,则无法在基类上使用 Func 。
如果您使用 Shadows,则可以在派生类中看到 Func 的唯一方法是将实例定义为 Derived,而不传递给基类的方法(X.Test 返回 Standard)。 我认为这是主要的:如果我使用 Shadows,该方法不会重载基本方法内的基本方法。
这就是重载的 OOP 方法。 如果我派生一个类并且在任何情况下我都希望调用一个方法,那么我必须使用重载。 对于我的对象的实例,没有办法返回“标准”(我认为除了使用反射)。 我认为智能感知会造成一些混乱。 如果我突出显示Y.Func,则会突出显示基类中的Func,但会执行派生类中的Func。
对于 Shadows,新方法只能直接访问。 例如 Overloads,但隐藏了基类的重载(我认为这是在编译之前返回的错误,因为您可以使用强制转换来调用它,例如使用重载隐式完成)。
I found another difference. See this:
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.
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.
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.
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).
如果您正在围绕现有控件编写包装器,则阴影可能非常有用。
例如围绕组合框。 通过隐藏 AutoCompleteSource,您可以防止将其设置为特殊类型组合框的非法值,即使它被转换为普通组合框也是如此。 或者在阴影属性中使用
mybase.AutoCompleteSource = value
之前进行一些预处理。Shadows can be very useful if you are writing a wrapper around an existing control.
For instance around a combobox. By shadowing the
AutoCompleteSource
you can prevent it to be set to a illegitimate value for your special kind of combobox even when it's cast to a normal combobox. Or do some pre-proccessing before you usemybase.AutoCompleteSource = value
in the shadowing property.VB 使用比 C# 更高级的 OOP 概念,要在 C# 的派生类中使用重写,您必须将方法标记为“虚拟”,Shadow 允许您在没有此方法的情况下进行重载。
阅读有关此内容的 MS 文档 https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/declared-elements/differences- Between-shadowing-and-overriding
VB use more advanced OOP concepts than C#, for use overriding in derived class in C# you MUST mark method as "vitrual", Shadow allow you make overload without this.
Read MS documentation about this https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/declared-elements/differences-between-shadowing-and-overriding
阴影的使用很少见,但却是真实的。 此外,您不能覆盖共享(静态)方法。 因此,如果您想“覆盖”共享方法,则必须对其进行隐藏。
The use of Shadows is rare but true. Moreover you cannot override a shared (static) method. So you must shadow a shared method if you want to "override" it.
我同意吉姆的观点。 我也从未找到过 Shadows 的合法用途。 通常,如果我看到它,我会认为代码的子部分需要稍微重构一下。
我想它在那里,以便您可以从无法控制源代码的程序集中隐藏方法。 在这种情况下,重构父类是不可能的。
I agree with Jim. I've never found a legitimate use for Shadows, either. Usually if I see it, I assume that sub-section of the code needs to be refactored a bit.
I suppose it is there so that you can shadow a method from an assembly in which you do not have control over the source code. In that case, refactoring the parent class would be impossible.
我想使用 System.Web.HttpContext.Current.Response 而不是 Response.redirect,并且需要方便地编码为 Response.redirect 。 我定义了一个名为 Response 的只读属性来隐藏基类中的原始属性。 我无法使用覆盖,因为该属性不可覆盖。 很方便:)
I wanted to use
System.Web.HttpContext.Current.Response
instead ofResponse.redirect
, and needed the convenience to code asResponse.redirect
. I defined a readonly property namedResponse
to shadow the original in a base class. I couldn't use overrides, since this property is not overridable. Very convenient:)我不认为 Shadows 真的是一个 OOP 概念。 覆盖表示您正在为祖先类中声明的方法/属性等提供新的或附加的功能。 阴影确实欺骗编译器认为父方法/属性等甚至不存在。
我对影子没有任何用处。 坚持覆盖。 VB 多年来提供的这些有用的小“功能”最终总会在某些时候给您带来悲伤。
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.
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.
覆盖是更正常的限定符。 如果子类以这种方式重新定义基类函数,则无论如何引用子对象(使用基类或子类引用),调用的都是子函数。
另一方面,如果子类函数遮蔽基类函数,则通过基类引用访问的子对象将使用该基类函数,尽管它是一个子对象。
仅当使用匹配的子引用访问子对象时,才使用子函数定义。
Overrides is 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.
On the other hand, if the child class function Shadows the 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.
阴影可能不会起到您想象的作用。
考虑以下类:
现在我使用它们:
您可能认为 oA 和 oB 是相同的,对吧?
没有。
oA.fx = 0 while oB.fx = 1
恕我直言,这是非常危险的行为,文档中几乎没有提到。
如果您使用了覆盖,它们将是相同的。
因此,虽然阴影有合法的用途,但您所做的很可能不是其中之一,应该避免。
Shadowing probably doesn't do what you think it does.
Consider the following classes:
Now I use them:
You probably think oA and oB are the same right?
Nope.
oA.fx = 0 while 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.
覆盖 - 扩展或创建方法的替代功能。
示例:添加或扩展窗口的 Paint 事件的功能。
Shadows - 重新定义继承的方法并强制将其用于使用该类型实例化的所有类。 换句话说,该方法不是重载而是重新定义的,并且基类方法不可用,从而强制使用类中声明的函数。 Shadows 保留或保留方法的定义,以便在修改基类方法时不会破坏该方法。
示例:强制所有“B”类使用其奇怪的 Add 定义,这样如果 A 类的 Add 方法被修改,则不会影响 B 的添加。 (隐藏所有基类“Add”方法。将无法从 B 的实例调用 A.Add(x, y, z)。)
Overrides - Extending or creating alternate functionality for a method.
Example: Add or extended the functionality of the Paint event of a window.
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.
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.)
有时,一个小例子确实有助于从技术角度理解差异。
Sometime a small example really helps understand the difference in a technical way.
“shadows”关键字本质上是说“如果访问此对象的人知道它属于此类型或其后代之一,则使用此成员;否则使用基成员。” 最简单的示例可能是基类 ThingFactory,其中包括返回 Thing 的“MakeNew”方法,以及从 ThingFactory 派生的类 CarFactory,其“MakeNew”方法始终返回派生类型为 Car 的 Thing。 如果例程知道它所持有的 ThingFactory 碰巧(更具体地说)是 CarFactory,那么它将使用影子 CarFactory.MakeNew(如果存在),它可以将返回类型指定为 Car。 如果例程不知道其 ThingFactory 实际上是 CarFactory,它将使用非影子 MakeNew(应调用内部受保护的可重写 MakeDerivedThing 方法)。
顺便说一句,阴影的另一个很好的用途是防止派生类访问不再起作用的受保护方法。 除了分配一个新成员之外,没有其他方法可以简单地从派生类中隐藏成员,但是可以通过使用该名称声明一个新的受保护空类来防止派生类对受保护成员执行任何操作。 例如,如果对一个对象调用 MemberwiseClone 会破坏它,则可以声明:
Note that this does not violate OOP principles like the Liskov Substitution Principle, since that only applies in cases where a derived class might be used in place of a base-class object. If Foo and Bar inherits from Boz, a method which accepts a Boz parameter may legitimately be passed in a Foo or Bar instead. On the other hand, an object of type Foo will know that its base-class object is of type Boz. It will never be anything else (e.g. it's guaranteed not to be a Bar).
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).
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:
Note that this does not violate OOP principles like the Liskov Substitution Principle, since that only applies in cases where a derived class might be used in place of a base-class object. If Foo and Bar inherits from Boz, a method which accepts a Boz parameter may legitimately be passed in a Foo or Bar instead. On the other hand, an object of type Foo will know that its base-class object is of type Boz. It will never be anything else (e.g. it's guaranteed not to be a Bar).
遮蔽示例:假设您要使用第三方组件中的函数,但该函数受到保护。 您可以通过简单的继承并公开一个基本上调用其基函数的隐藏函数来绕过此约束:
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:
我认为人们在这里确实遇到了两种情况,而且都是合理的。 您实际上可以将它们分解为基类设计者和多年后实现子类且无法修改基类的开发人员。 所以,是的,如果你有这种奢侈的话,最好的办法就是超越。 这是干净的 OOD 方法。
另一方面,您可能会遇到类似上面给出的示例,其中您处于该等式的另一端,必须实现子类,并且您无法更改需要重写的方法未标记为可重写的事实。 举个例子,
在这种情况下,我从 Winform 控件类继承我的类,不幸的是,它没有被标记为可重写。 此时,我面临着使代码“纯粹”或使其更易于理解的问题。 该控件的客户端只是想调用 control.Focus() 并且可能不关心。 我可以将此方法命名为 FocusSearchText() 或 Focus2 等,但我相信上述方法对于客户端代码来说要简单得多。 确实,如果客户端随后将此控件强制转换为基类并调用 Focus,我的代码将不会执行。 但这是相当遥远的。
最终,这取决于你必须做出的判断。
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.
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
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.
In the end it comes down to a judgement call, and one you'll have to make.
这是最近的 MSDN 链接:
隐藏之间的差异覆盖
遮蔽可防止后续基类修改引入您已在派生类中定义的成员。
您通常在以下情况下使用遮蔽:
**您预计您的基类可能会被修改以定义与您的名称相同的元素。*
**您希望能够自由地更改元素类型或调用序列.*
(我还没有调查范围和类型的用法)
This is a recent MSDN link:
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)
这是代码的答案。
您可以复制粘贴此内容并自行尝试。 正如您所看到的,阴影是默认行为,并且当您没有显式编写阴影修饰符时,Visual Studio 会在阴影发生时向您发出警告。
注意:对我来说,我从未使用过对子对象的基类引用。 对于这种情况,我总是使用接口。
Well here is the answer by Code.
You can copy paste this and try it yourself. As you can see the shadowing is the default behavior, and Visual Studio does warn you when shadowing is going on without you explicitly writing the shadow modifier.
Note: For me, I have never used a Base class reference to a child object. For such cases I always use Interfaces.