【问题标题】:How does "Private Shadows" work in VB.NET“私人阴影”如何在 VB.NET 中工作
【发布时间】:2013-09-25 04:13:27
【问题描述】:

我有这样的 3 个类的层次结构:

`DrawingObject` > `RectangularDrawingObject` > `Rectangle`

DrawingObject 有以下成员:

Protected Overridable Function ToXMLInternal(type As Type) As String

我只想将此函数公开给第二级(即RectangularDrawingObject)并在第三级的类中隐藏它(Rectangle 等),所以我在RectangularDrawingObject 中隐藏它:

Private Shadows Function ToXMLInternal(type As Type) As String

在这里考虑Private。由于我已经遮蔽了,基础版本应该不再可供 3 级课程访问。而且由于它是私有的,所以这个版本也不应该被访问。但我可以在Rectangle 类中访问它(第一级版本)。为什么呢?解决方法是什么?

编辑:

关于妮可的回答:

当从外部访问 Rectangle 时,RectangularDrawingObject 的 ToXMLInternal() 仍然有效。

这是不正确的。从外部访问 Rectangle 时,ToXMLInternal() 不可用/不应该可用,因为它充其量是受保护的。

如果您从 Rectangle 内部调用 ToXMLInternal(),则不同。那么调用者就知道有阴影的方法,用这个代替了RectangularDrawingObject的方法。

RectangularDrawingObject 的方法阴影方法。那么这段话是什么意思呢?

如果我正确理解您的观点,那么Private Shadows 就不可能工作或被要求。是的?然后 VS 应该警告它说“'Private' 和 'Shadows' 不能组合”,就像它对许多其他关键字(例如 PrivateOverridable)所做的那样。

【问题讨论】:

  • “我只想将此函数公开给第 2 级,并从第 3 级的类中隐藏它”——这表明继承不是正确的机制。你应该只让Rectangle派生自DrawingObject,如果你可以对DrawingObject做的所有事情,你也可以对Rectangle做任何事情

标签: .net vb.net oop


【解决方案1】:

Shadows 隐藏一个成员的实现,并在其可访问性上下文中提供一个新的实现。这意味着在您的情况下,RectangularDrawingObject's ToXMLInternal() 在从外部访问 Rectangle 时仍然有效。调用者只是不知道有阴影方法。他为什么会?毕竟方法是私有的。

如果您从Rectangle 内部调用ToXMLInternal(),则不同。然后调用者知道有阴影方法,并使用此方法代替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。不过,这有多大的合理性值得商榷。

编辑 2

又想了想与Overrides 的区别。

如果上例中的遮蔽方法是公开的,那么

Dim obj As New B()
obj.Method()

将输出“来自 B”。当然。但是,如果我们将obj 称为A

Dim obj As A = New B()
obj.Method()

那么输出是“来自 A”。那是因为阴影方法仍然存在,通过A 访问obj,您可以访问原始方法。 Overrides 将完全替换该方法,甚至上面的示例也会输出“From B”,因为obj 中不再存在原始方法。

【讨论】:

  • 谢谢尼科。我很难理解你的答案。得到了一些观察。太长了,无法发表评论。请检查我上面的编辑。
  • 我现在更清楚地看到了你的观点。感谢您花时间解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-13
相关资源
最近更新 更多