VB.NET의 '그림자'대 '재정의'
두 키워드 Shadows 및 Overrides 의 의미는 무엇입니까 ? 그들이하는 일과 어떤 맥락이 선호 되는가?
Shadows가 실제로 OOP 개념이라고 생각하지 않습니다. 재정의는 상위 클래스에서 선언 된 메서드 / 속성 등에 대해 새 기능이나 추가 기능을 제공하고 있음을 나타냅니다. Shadows는 실제로 컴파일러가 부모 메서드 / 속성 등이 존재하지 않는다고 생각하도록 속입니다.
나는 그림자를 사용하지 않습니다. 재정의에 충실하십시오. VB가 수년 동안 제공 한 이러한 유형의 유용한 작은 "기능"은 항상 언젠가는 슬픔을 유발합니다.
재정의 는 더 일반적인 한정자입니다. 자식 클래스가 이런 방식으로 기본 클래스 함수를 재정의하면 자식 개체가 참조되는 방법 (기본 클래스 또는 자식 클래스 참조 사용)에 관계없이 호출되는 자식 함수입니다.
반면에 자식 클래스 함수 가 기본 클래스 함수를 숨기면 기본 클래스 참조를 통해 액세스 된 자식 개체는 자식 개체 임에도 불구하고 해당 기본 클래스 함수를 사용합니다.
자식 함수 정의는 일치하는 자식 참조를 사용하여 자식 개체에 액세스하는 경우에만 사용됩니다.
섀도 잉은 아마도 당신이 생각하는대로하지 않을 것입니다.
다음 클래스를 고려하십시오.
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 이것은 매우 위험한 행동이며 문서에서 거의 언급되지 않습니다.
재정의를 사용했다면 동일합니다.
따라서 그림자에 대한 합법적 인 용도가 있지만, 당신이하는 일이 그 중 하나가 아니므로 피해야합니다.
재정의-메서드에 대한 대체 기능 확장 또는 생성.
예 : 창의 그림판 이벤트 기능을 추가하거나 확장합니다.
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-상속 된 메서드를 재정의하고 해당 유형으로 인스턴스화 된 모든 클래스에 대해 강제로 사용합니다. 즉, 메서드가 오버로드되지 않고 재정의되고 기본 클래스 메서드를 사용할 수 없으므로 클래스에서 선언 된 함수를 강제로 사용해야합니다. Shadows는 기본 클래스 메서드가 수정 되어도 삭제되지 않도록 메서드 정의를 유지하거나 유지합니다.
예 : 모든 "B"클래스가 이상한 추가 정의를 사용하도록 강제하여 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
때로는 작은 예가 기술적으로 차이를 이해하는 데 도움이됩니다.
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
"shadows"키워드는 기본적으로 "이 개체에 액세스하는 사람이이 유형 또는 하위 항목 중 하나임을 알고있는 경우이 멤버를 사용하고 그렇지 않으면 기본 멤버를 사용하십시오."라고 말합니다. 이에 대한 가장 간단한 예는 Thing을 반환하는 "MakeNew"메서드와 ThingFactory에서 파생 된 CarFactory 클래스를 포함하는 기본 클래스 ThingFactory 일 수 있습니다.이 클래스는 "MakeNew"메서드가 항상 파생 된 유형 Car가 될 Thing을 반환합니다. 루틴이 보유하고있는 ThingFactory, 특히 CarFactory가 발생한다는 것을 알고있는 경우, 반환 유형을 Car로 지정할 수있는 그림자 CarFactory.MakeNew (존재하는 경우)를 사용합니다. 루틴이 ThingFactory가 실제로 CarFactory인지 모르는 경우
덧붙여서, 섀도우의 또 다른 좋은 사용은 파생 클래스가 더 이상 작동하지 않는 Protected 메서드에 액세스하지 못하도록하는 것입니다. 새 멤버를 할당하는 것 외에 파생 클래스에서 멤버를 단순히 숨길 수있는 방법은 없지만 해당 이름으로 새 보호 된 빈 클래스를 선언하여 파생 클래스가 보호 된 멤버로 작업을 수행하는 것을 방지 할 수 있습니다. 예를 들어, 개체에 대해 MemberwiseClone을 호출하면 개체가 중단되는 경우 다음을 선언 할 수 있습니다.
보호 된 그림자 클래스 MemberwiseClone 수업 종료이것은 Liskov Substitution Principle과 같은 OOP 원칙을 위반하지 않습니다. 이는 파생 클래스가 기본 클래스 개체 대신 사용될 수있는 경우에만 적용되기 때문입니다. Foo 및 Bar가 Boz에서 상속하는 경우 Boz 매개 변수를 허용하는 메서드가 합법적으로 Foo 또는 Bar로 대신 전달 될 수 있습니다. 반면에 Foo 유형의 객체는 기본 클래스 객체가 Boz 유형임을 알게됩니다. 다른 어떤 것도 아닙니다 (예 : 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
사람들이 여기에서 취하고있는 두 가지 시나리오가 있고 둘 다 합법적이라고 생각합니다. 기본 클래스 디자이너와 몇 년 후 기본 클래스를 수정할 수없는 하위 클래스를 구현하는 개발자로 세분화 할 수 있습니다. 네, 가장 좋은 방법은 그 사치가 있다면 무시하는 것입니다. 이것은 깨끗한 OOD 접근 방식입니다.
다른 한편으로, 하위 클래스를 구현해야하는이 방정식의 다른 쪽 끝에있는 위에 주어진 예제와 같은 것이있을 수 있으며 재정의해야하는 메서드가 재정의 가능으로 표시되지 않는다는 사실을 변경할 수 없습니다. 예를 들어
Public Shadows Function Focus() As Boolean
txtSearch.Focus()
Return MyBase.Focus()
End Function
이 경우 불행히도 재정의 가능으로 표시되지 않은 Winform 컨트롤 클래스에서 클래스를 상속합니다. 이 시점에서 저는 코드를 "순수"하거나 이해하기 쉽게 만드는 일에 직면했습니다. 이 컨트롤의 클라이언트는 단순히 control.Focus ()를 호출하기를 원하며 아마도 상관하지 않을 것입니다. 이 메서드의 이름을 FocusSearchText () 또는 Focus2 등으로 지정할 수 있었지만 위의 방법이 클라이언트 코드에 대해 훨씬 더 간단하다고 생각합니다. 클라이언트가이 컨트롤을 기본 클래스로 캐스팅하고 Focus를 호출하면 내 코드가 실행되지 않는 것은 사실입니다. 그러나 그것은 상당히 멀리 떨어져 있습니다.
결국 그것은 판단 호출로 귀결되며, 하나는해야합니다.
이것은 최근 MSDN 링크입니다 : 섀도 잉과 재정의의 차이점
섀도 잉은 파생 클래스에 이미 정의한 멤버를 도입하는 후속 기본 클래스 수정으로부터 보호합니다. 일반적으로 다음과 같은 경우에 섀도 잉을 사용합니다.
** 동일한 이름을 사용하는 요소를 정의하기 위해 기본 클래스가 수정 될 수 있습니다. *
** 요소 유형을 변경하거나 시퀀스를 호출 할 자유를 원합니다. *
(아직 범위 및 유형과 관련하여 사용법을 조사하지 않았습니다)
Shadow를 사용하면 재정의로 수행 할 수없는 특정 작업을 수행 할 수 있습니다.
제 경우에는 일반 기능을 가진 여러 테이블 클래스가 있습니다. 그러나 누구를 위해 컬렉션 자체가 다른 유형입니다.
Public Class GenericTable
Protected Friend Overridable Property Contents As System.Collections.Generic.List(Of GenericItem)
... do stuff ...
End Class
그런 다음 특정 isntances가 있습니다.
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 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).
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.
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:)
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.
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.
참고 URL : https://stackoverflow.com/questions/463209/shadows-vs-overrides-in-vb-net
'code' 카테고리의 다른 글
JSHint에서 camelcase 변수 무시 (0) | 2020.11.20 |
---|---|
C ++ 구문 "A :: B : A {};"는 무엇입니까? (0) | 2020.11.20 |
.Net 이전 vb left (string, length) 함수와 동일합니까? (0) | 2020.11.20 |
Visual Studio가 배치 파일에 잘못된 문자를 삽입합니다. (0) | 2020.11.20 |
Foundation Framework와 Core Foundation Framework의 차이점은 무엇입니까? (0) | 2020.11.20 |