Переопределение свойства ReadOnly в подклассе для его чтения / записи (VB.NET или C#)

Это кажется невозможным в VB.NET со свойствами, поскольку сам оператор property должен описывать, является ли он ReadOnly или нет.

в моем примере ниже, это не позволяет мне сделать ReadWriteChild компиляции. Думаю, я мог бы заставить родителя читать/писать, а затем заставить сеттера ReadOnlyChild ничего не делать, но это кажется немного хаки. Лучшей альтернативой, по-видимому, является отказ от свойств в пользу методов 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 ответов


учитывая, что вы пытаетесь выполнить, и с образцом кода, который вы опубликовали, 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

В основном маркировка общего свойства как публичного, но предоставление более ограничительной области для сеттера (или геттера).

основной проблемой в вашем случае является базовый класс MustInherit (т. е. абстрактный). Поскольку свойство, которое вы определяете, помечено как MustOverride, вы не можете предоставить реализацию по умолчанию (т. е. она тоже абстрактна), и это включает в себя контуры "Get" и "Set", поэтому, какую бы "общую" область вы ни дали этому объявлению абстрактного свойства, VB.NET заставит вас использовать эту область для и геттеры и сеттеры в производных классах.

наличие квалификатора ReadOnly в свойстве базового класса заставит все производные классы и реализации этого свойства также быть только для чтения. Исключение квалификатора ReadOnly по-прежнему не будет работать, так как любая область, которую вы даете абстрактному свойству, будет областью, которую вы должны применить как к сеттерам, так и к геттерам в производных реализациях.

например:

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

(обратите внимание на частную область видимости на сеттере). Это не будет работать как VB.NET настаивает на том, что, поскольку вы переопределяете свойство базовых классов, все ваше свойство должно иметь ту же область, что и переопределяемое свойство (в данном случае публичный).

попытка сделать абстрактное свойство базового класса защищенным также не будет работать, так как вам потребуется реализовать свойство на том же уровне области видимости, что и в вашем базовом классе (т. е. защищенном). Обычно, когда не переопределяется абстрактное определение базового класса с определенным уровнем области видимости, вы можете дать геттеру или сеттеру больше ограничительный уровень охвата, но вы не можете дать ему меньше ограничительный уровень охвата.

таким образом:

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

(обратите внимание на общественный охват геттера). Не работает также из-за того, что публичная область является менее ограничительной, чем общая область защищаемых свойств, и более того, не имеет того же уровня области, который определен в объявлении абстрактного свойства базового класса.

Если дизайн ваших классов, как вы упоминаете в своем вопросе, я лично, пошел бы с геттером и сеттером" java-style методы поскольку они могут быть объявлены отдельно с их собственными уровнями области видимости.


может быть длинный выстрел ... учитывая, что мое знание VB.NET минимально ...

в C# вы можете указать видимость метода доступа к свойству независимо от свойства:

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

в этом примере классы ребенок может получить доступ к settor, но и другие классы не могут.

также обратите внимание, что переопределения могут иметь большую видимость, чем то, что они переопределяют, поэтому вы можете сделать это:

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

не могли бы вы сделать что-то подобное в VB.NET ?


убедитесь, что MrEdmuno правильно, что вы можете использовать тень. Однако, похоже, вы не можете напрямую затенять то, что помечено 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

к сожалению, у меня нет visual studio, поэтому я не могу подтвердить.

вы смотрели на использование теней, это эффективно то же самое, что сказать "новый" в объявлении свойства C#.


Не пытайтесь переопределить свойство, так как оно не является виртуальным. Переопределите методы OnReadOnlyChanged и обработайте свой бизнес там. Удачи!--1-->


чтобы обратиться к тому, что предложил Беван, в VB.NET вы можете объявить свойство как имеющее общедоступный геттер и защищенный сеттер следующим образом:

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

вам нужно добавить еще один уровень иерархии; к сожалению, единственный способ правильно охватить вещи-использовать вложенные классы:

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