3

Conceptually it seems like a derived class should be able to override a readonly property with a read write property. Why isn't this possible?

Public Class Base

    Protected _name As String
    Public Overridable ReadOnly Property Name() As String
        Get
            return _name
        End Get
    End Property

End Class

Public Class Derived
    Inherits Base

    Public Overrides Property Name() As String
        Get
            Return MyBase.Name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property

End Class
PeterM
  • 2,372
  • 1
  • 26
  • 35
  • 3
    I have a better question: why should a SUBclass ever be able to set a readonly property in its base class??? – Brian Driscoll Mar 23 '11 at 13:58
  • Good question, but it can only be answered by someone from Microsoft who worked on the design of the OO implementation of the language. – Meta-Knight Mar 23 '11 at 14:01
  • So, I just shouldn't ever be doing this? – PeterM Mar 23 '11 at 14:01
  • @Brian Driscol: It's actually a very good pattern for an interface or abstract base class to provide a read-only property, and for a derived interface or class to provide a mutable version. If that had been done with IList, for example, a class that needed to read (but didn't need to write) a passed-in array-like collection of Animal would be able to accept a List. Incidentally, it's also good to have a immutable class, separately derived from the same base, which can only be set via its constructor. – supercat Jul 21 '11 at 19:00

3 Answers3

2

A property is a "construct" that has accessor methods.

When you put the Overridable keyword in a property, it is applied to its accessors.

For a read-only property, you only have the get accessor, so it is Overridable.

In your derived class you mark the property as Overrides, but you can only override the get accessor, because it's the only Overridable accessor. If you then include a set accessor, there's nothing for it to override, and so you get that error.

I suppose this is possible in the IL, but not in VB.NET or C#.

What you can do is shadow a subclass definition, but then you won't have the same behavior as with overrides, with regards to polymorphic dispatch:

Public Class Derived
    Inherits Base

    Public Shadows Property Name() As String
        Get
            Return MyBase.Name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property

End Class

Or you can provide an empty setter in the base class (or one that throws a NotSupportedException), that will be Overridable in the subclass.

Or you can provide another method to do the setting, outside of the property definition:

Public Sub SetName(ByVal value As String)
    _name = value
End Sub
Jordão
  • 55,340
  • 13
  • 112
  • 144
  • 1
    It's actually possible in C#. The only time I've needed to use it is if I declare an interface with a read-only property, but want the implementing class to have the property be read-write. It's pretty annoying that you can't do that in VB, even with interfaces. – siride Mar 23 '11 at 14:19
  • It's not possible in C# with base classes. But yes, it's possible with interfaces. – Jordão Mar 23 '11 at 14:24
  • yes, you are right. I had assumed so because it worked with interfaces and I've only ever had the need to do it with interfaces. – siride Mar 23 '11 at 14:40
  • 1
    VB can now set readonly properties in the constructor, and override interface readonly properties to add a setter. – Brain2000 Oct 24 '17 at 14:35
2

I disagree, it seems nonsense to change the ReadOnly access of a base classes property.

The rules for VBs ReadOnly are carefully defined: http://msdn.microsoft.com/en-us/library/z2b2c2ka.aspx#Y300

The base class author(s) get to mark a property as readonly.

You wont know what the consequence of changing a property's value is.

Mesh
  • 6,262
  • 5
  • 34
  • 53
  • An class which is semantically defined as *IMMUTABLE* should not have mutable subclasses (nor should it be inheritable outside its assembly), but read-only does not imply immutable. There are many situations in which it may be useful to have a method accept other objects which might be mutable or immutable, without caring which; the proper way to do this is to have a read-only (possibly abstract) base class, and derive both mutable and immutable classes from that. – supercat Jul 21 '11 at 19:08
1

I don't think you should really be doing this - the VB.NET Language simply doesn't allow for it. My guess as to why is because a property on an Interface uses the ReadOnly modifer to determine if it should have a Getter / Setter, rather than the presence of a getter / setter. The closest you could get is change the base to have a setter which throws an Exception, and the Derived class override it:

Public Class Base
    Protected _name As String
    Public Overridable Property Name() As String
        Get
            Return _name
        End Get

        Set(ByVal value As String)
            Throw New Exception("Can't do it")
        End Set
    End Property
End Class

Public Class Derived
    Inherits Base
    Public Overrides Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property
End Class
vcsjones
  • 138,677
  • 31
  • 291
  • 286