覆盖子类中的ReadOnly属性以使其成为读/写(VB.NET或C#)

时间:2009-02-16 19:55:10

标签: c# vb.net inheritance properties readonly

这在带有属性的VB.NET中似乎不可能,因为属性语句本身必须描述它是否为ReadOnly

在下面的示例中,它不允许我进行ReadWriteChild编译。我想我可以让父读/写,然后让ReadOnlyChild的setter不做任何事情,但这似乎有点hacky。在这种情况下,最好的替代方案似乎是放弃属性而采用getter / setter方法。

Public MustInherit Class Parent

    Public MustOverride ReadOnly Property Foo() As String

End Class

Public Class ReadOnlyChild
    Inherits Parent

    Public Overrides ReadOnly Property Foo() As String
        Get
            ' Get the Property
        End Get
    End Property

End Class

Public Class ReadWriteChild
    Inherits Parent

    Public Overrides Property Foo() As String
        Get
            ' Get the property.
        End Get
        Set(ByVal value As String)
           ' Set the property.
        End Set
    End Property

End Class

7 个答案:

答案 0 :(得分:6)

鉴于您要完成的任务,以及您发布的示例代码,VB.NET将不允许您这样做。

通常,你可以像这样在VB.NET中声明一个属性:

Public Class qwqwqw
  Public Property xyz() As String
      Get
          Return ""
      End Get
      Private Set(ByVal value As String)
          '
      End Set
  End Property
End Class

基本上将整体属性标记为公共属性,但为setter(或getter)提供更具限制性的范围。

您的案例中的主要问题是MustInherit(即抽象)基类。由于您在其中定义的属性标记为MustOverride,因此您无法提供默认实现(即,它也是抽象的),这包括“获取”和“设置”轮廓,因此,无论哪个“整体” “你给这个抽象属性声明的范围,VB.NET将强制你使用这个范围两者派生类中的getter和setter。

在基类的属性上使用ReadOnly限定符将强制所有派生类和此属性的实现也是ReadOnly。抛弃ReadOnly限定符仍然不起作用,因为您给abstract属性的任何范围都是必须应用于派生实现中的setter和getter的范围。

例如:

Public MustInherit Class Parent
  Public MustOverride Property Foo() As String
End Class

Public Class ReadOnlyChild
  Inherits Parent

  Public Overrides Property Foo() As String
    Get
        '
    End Get
    Private Set(ByVal value As String)
        '
    End Set
  End Property
End Class

(注意setter上的私有作用域)。这不起作用,因为VB.NET坚持认为,因为你要覆盖基类属性,所以你的整个属性必须与你所覆盖的属性具有相同的范围(在这种情况下,公共)。

尝试使基类的抽象属性受到保护也不起作用,因为您需要在与基类中声明的作用域相同的级别(即受保护的)上实现该属性。通常,在不使用特定的作用域级别覆盖基类的抽象定义时,可以为getter或setter提供 more 限制性作用域级别,但是不能给它 less

因此:

Public MustInherit Class Parent
  Protected MustOverride Property Foo() As String       
End Class

Public Class ReadOnlyChild
  Inherits Parent

  Protected Overrides Property Foo() As String
      Public Get
          '
      End Get
      Set(ByVal value As String)
          '
      End Set
  End Property
End Class

(注意getter上的公共范围)。由于公共范围的限制性低于受保护的整体属性范围,而且不是与基类的抽象属性声明中定义的范围级别相同,因此不起作用。

如果你的课程设计正如你在问题中提到的那样,我个人会选择“java风格”的getter和setter 方法,因为它们可以用自己的方式单独声明范围界定。

答案 1 :(得分:3)

可能是一个远景......鉴于我对VB.NET的了解很少......

在C#中,您可以独立于属性指定属性访问者的可见性:

public virtual string Name
{
    get { ... }
    protected set { ... }
}

在此示例中,子类可以访问settor,但其他类不能。

另请注意,覆盖可以提供比覆盖更高的可见性 - 因此您可以执行此操作:

public overide string Name
{
    get { ... }
    public set { ... }
}

你能在VB.NET中做这样的事情吗?

答案 2 :(得分:2)

确认MrEdmuno是否正确,您可以使用Shadow。然而,看起来你不能直接遮住标记为MustInherit的东西,所以你需要继承到一个类(父2)...然后进入你的readonly(实际上考虑它你可能不需要使用阴影,如果你继承成一个班级)

我认为我的评论问题仍然存在,为什么你需要这样做?如果它们是您自己的类,您最好修改它们,还是作为接口实现?

Public MustInherit Class Parent

    Public MustOverride ReadOnly Property Foo() As String

End Class

Public Class ReadOnlyChild
    Inherits Parent

    Public Overrides ReadOnly Property Foo() As String
        Get
            'Get the Property
            Return "Return"
        End Get
    End Property

End Class

Public Class Parent2
    Inherits Parent

    Public Overrides ReadOnly Property Foo() As String
        Get
            Return "Return 2"
        End Get
    End Property
End Class

Public Class ReadWriteChild
    Inherits Parent2

    Public Shadows Property Foo() As String
        Get
            '// Get the property.
            Return "2"
        End Get
        Set(ByVal value As String)
            '** Set something
        End Set
    End Property

答案 3 :(得分:0)

不幸的是我在这里没有视觉工作室所以我无法确认。

你有没有看过使用Shadows,这实际上和在C#属性声明中说“new”一样。

答案 4 :(得分:0)

要解决Bevan建议的问题,在VB.NET中,您可以将属性声明为具有公共getter和受保护的setter,如下所示:

Private _ExpectedTotalRoyalties As Decimal

Public Property ExpectedTotalRoyalties() As Decimal
    Get
        Return _ExpectedTotalRoyalties
    End Get
    Protected Set(ByVal value As Decimal)
        If Not _ExpectedTotalRoyalties.Equals(value) Then
            _ExpectedTotalRoyalties = value
            SendPropertyChanged("ExpectedTotalRoyalties")
        End If
    End Set
End Property

答案 5 :(得分:0)

不要尝试覆盖该属性,因为它不是虚拟的。覆盖OnReadOnlyChanged方法并在那里处理您的业务。祝你好运

答案 6 :(得分:0)

您需要添加另一级别的层次结构;不幸的是,真正确定范围的唯一方法是使用嵌套类:

Public Class IntermediateClassForPrivateInheritanceOnly
  Inherits Parent
  Public Overrides ReadOnly Property Foo() As String
  ' etc.
  Private Sub New(whatever)
    MyBase.New(whatever)
  End Sub

  ' Most other stuff for the class goes here.

  Public Class ReadWriteChild
    Inherits IntermediateClassForPrivateInheritanceOnly
    Shadows Property Foo()
    ' etc.
    Public Sub New(whatever)
      MyBase.New(whatever)
    End Sub
  End Class
End Class

Public Class ReadWriteChild  ' Would use an alias, if such things existed
  Inherits IntermediateClassForPrivateInheritanceOnly
  Public Sub New(whatever)
    MyBase.New(whatever)
  End Sub
End Class