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

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

В моем примере ниже, это не позволяет мне сделать компиляцию ReadWriteChild. Я полагаю, я мог бы сделать родительские права на чтение / запись, а затем установщик ReadOnlyChild ничего не делал, но это выглядит как хакерство. В этом случае лучшая альтернатива - отказаться от свойств в пользу методов получения / установки.

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 ]

6 голосов
/ 17 февраля 2009

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

Попытка сделать защищенное абстрактное свойство базового класса также не будет работать, поскольку тогда вам потребуется реализовать свойство на том же уровне области видимости, что и объявленный в вашем базовом классе (т.е. защищенном). Обычно, если не переопределять абстрактное определение базового класса определенным уровнем области видимости, вы можете задать для ограничителя или ограничителя 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

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

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

3 голосов
/ 16 февраля 2009

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

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

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

В этом примере дочерние классы могут обращаться к сеттеру, но другие классы не могут.

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

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

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

2 голосов
/ 17 февраля 2009

Подтвердите, что MrEdmuno верен в том, что вы можете использовать Shadow. Однако кажется, что вы не можете напрямую затенять что-то, помеченное как MustInherit, поэтому вам нужно наследовать в класс (Parent 2) ... затем в свой только для чтения (на самом деле, думая об этом, вам, вероятно, не нужно использовать тени, если наследовать в класс)

Я думаю, что мой вопрос с комментариями остается в силе, зачем вам это нужно? Если они являются вашими собственными классами, вам лучше их изменить или реализовать как интерфейс?

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
0 голосов
/ 20 декабря 2010

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

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
0 голосов
/ 21 июня 2010

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

0 голосов
/ 03 мая 2009

Чтобы учесть то, что предложил Беван, в 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
0 голосов
/ 17 февраля 2009

К сожалению, у меня здесь нет визуальной студии, поэтому я не могу подтвердить.

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

...