Overriding ReadOnly Property in a subclass to make it Read/Write (VB.NET or C#)

一个人想着一个人 提交于 2019-12-04 05:18:16
CraigTP

Given what you're trying to accomplish, and with the sample code you posted, VB.NET will not let you do this.

Ordinarily, you can declare a property in VB.NET like so:

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

Basically marking the overall property as public, but giving a more restrictive scope to the setter (or getter).

The main problem in your case is the MustInherit (i.e. abstract) base class. Since the property you're defining in there is marked as MustOverride, you can't provide a default implementation (i.e. it, too, is abstract), and this includes the "Get" and "Set" outlines, therefore, whichever "overall" scope you give to this abstract property declaration, VB.NET will force you to use this scope for both the getters and setters within derived classes.

Having the ReadOnly qualifier on the base class's property will force all derived classes and the implementations of this property to also be ReadOnly. Leaving off the ReadOnly qualifier still will not work, since whatever scope you give to the abstract property will be the scope you must apply to both the setters and getters within derived implementations.

For example:

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

(Note the Private scoping on the setter). This will not work as VB.NET is insisting that since you're overriding the base classes property, your entire property must have the same scope as the property you're overriding (in this case, public).

Attempting to make the base class's abstract property protected will not work either, since you would then be required to implement the property at the same level of scoping as it's declared in your base class (i.e. protected). Ordinarily, when not overriding a base class's abstract definition with a specific scoping level, you can give a getter or setter a more restrictive scoping level, but you can't give it a less restrictive scoping level.

Therefore:

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

(Note the public scoping on the getter). Doesn't work either due to the public scope being less restrictive than the overall property scope of protected, and moreover, not of the same scoping level as defined on the base class's abstract property declaration.

If the design of your classes is as you mention in your question, I personally, would go with a "java-style" getter and setter methods as they can then be declared separately with their own scoping levels.

Might be a longshot ... given that my knowledge of VB.NET is minimal ...

In C# you can specify the visibility of a property accessor independently of the property:

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

In this example, child classes can access the settor, but other classes cannot.

Also note that overrides can have greater visibility than what they override - so you can do this:

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

Could you do something like this in VB.NET ?

spacemonkeys

Confirm that MrEdmuno is correct in that you can use Shadow. However it appears you can't directly shadow something that is marked MustInherit, so you need to inherit into a class (Parent 2) ... then into your readonly (actually thinking about it you probably don't need to use shadows if you inherit into a class)

I think my comment question still stands, why are you needing to do this ? If they are your own classes would you be better to modify those, or implement as a interface ?

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

Unfortunatly I haven't got visual studio on here so I can't confirm.

Have you looked at using Shadows, this is effectivly the same as saying "new" in C# property declaration.

Do not try to override the property since it is not virtual. Override the OnReadOnlyChanged methods and handle your business there. Good luck

Mark

To address what Bevan suggested, in VB.NET you can declare a property as having a public getter and a protected setter, as follows:

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
supercat

You need to add another level of hierarchy; unfortunately, the only way to really scope things properly is to use nested classes:

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!