我有3个类的层次结构,如下所示:
`DrawingObject` > `RectangularDrawingObject` > `Rectangle`
DrawingObject
有以下成员:
Protected Overridable Function ToXMLInternal(type As Type) As String
我想将此函数仅公开到第二级(即RectangularDrawingObject
)并将其隐藏在第3级(Rectangle
等)的类中,因此我将其隐藏在RectangularDrawingObject
中:
Private Shadows Function ToXMLInternal(type As Type) As String
在此处考虑Private
。由于我已经隐藏了,因此第3级课程不再可以访问基础版本。由于它是私有的,因此也不应该访问此版本。但是我能够在Rectangle
课程中访问它(第一级版本)。为什么会这样?什么是解决方法?
修改
关于Nico的回答:
从外部访问Rectangle时,RectangularDrawingObject的ToXMLInternal()仍然有效。
这不正确。从外部访问Rectangle
时,ToXMLInternal()不是/不应该是可用的,因为它最多是受保护的。
如果从Rectangle内部调用ToXMLInternal(),则它是不同的。然后调用者知道有一个阴影方法并使用它而不是RectangularDrawingObject的方法。
RectangularDrawingObject的方法是阴影方法。那段经文到底是什么意思?
如果我理解你的观点,那么Private Shadows
就不会有任何工作或被要求的情况。是?然后,VS应警告它说''私有'和'阴影'不能合并“,就像许多其他关键字一样(例如Private
和Overridable
)。
答案 0 :(得分:2)
Shadows
隐藏成员的实现,并在其可访问性上下文中提供新的成员。这意味着,在您从外部访问RectangularDrawingObject's
时,ToXMLInternal()
Rectangle
仍然有效。调用者只是不知道有阴影方法。他为什么要这样?毕竟这个方法是私密的。
如果您从ToXMLInternal()
内部致电Rectangle
,则会有所不同。然后调用者知道存在阴影方法并使用它而不是RectangularDrawingObject's
方法。
问题是,为什么你甚至想要这种行为?在遮蔽是一个好主意的情况下,可能会出现罕见的情况,但总的来说,这是对您的设计的误解。
无法使子类的公共成员无法访问子类。这与整个面向对象的范式相矛盾。您只能更改子类中的行为。
让我们考虑一下这个简单的类层次结构:
Class A
Public Sub Method()
Console.WriteLine("From A")
End Sub
End Class
Class B
Inherits A
Private Shadows Sub Method()
Console.WriteLine("From B")
End Sub
End Class
现在,如果我们执行以下操作:
Sub Main()
Dim obj As New B()
obj.Method()
End Sub
然后输出为“From A”。您从外部查看类B
,因此看不到有阴影方法。该方法是私有的。因此,使用类A
中继承的公共方法,并将“From A”打印到控制台。
如果我们向课程B
添加另一种方法:
Public Sub CallMethod()
Method()
End Sub
并在Main()
obj.CallMethod()
然后CallMethod()
在类B
内,可以看到它立即使用的私有阴影方法。结果输出为“From B”。
您甚至可以使用
从CallMethod
访问继承(非阴影)方法
MyBase.Method()
将输出“From A”。
请记住,基类的每个公共方法也可用于子类。您最多可以使用另一个公共方法来隐藏此方法,但无法完全隐藏该方法。 Shadows
的C#等价物是new
,它也很好地描述了行为。保留原始实现并在类中添加新实现。
如最后一个示例所示,在某些情况下可能会使用Private Shadows
。虽然,这可能是多么合理。
关于与Overrides
的区别的另一个想法。
如果上例中的阴影方法是公开的,那么
Dim obj As New B()
obj.Method()
将输出“From B”。当然。但是,如果我们将obj
称为A
:
Dim obj As A = New B()
obj.Method()
然后输出是“从A”。这是因为阴影方法仍然存在,并且通过obj
访问A
,您可以访问原始方法。 Overrides
将完全取代该方法,甚至上面的示例也会输出“From B”,因为原始方法在obj
中不再存在。