Переопределение свойства 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