这在带有属性的VB.NET中似乎不可能,因为属性语句本身必须描述它是否为ReadOnly
。
在下面的示例中,它不允许我进行ReadWriteChild
编译。我想我可以让父读/写,然后让ReadOnlyChild的setter不做任何事情,但这似乎有点hacky。在这种情况下,最好的替代方案似乎是放弃属性而采用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
答案 0 :(得分:6)
鉴于您要完成的任务,以及您发布的示例代码,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
基本上将整体属性标记为公共属性,但为setter(或getter)提供更具限制性的范围。
您的案例中的主要问题是MustInherit(即抽象)基类。由于您在其中定义的属性标记为MustOverride,因此您无法提供默认实现(即,它也是抽象的),这包括“获取”和“设置”轮廓,因此,无论哪个“整体” “你给这个抽象属性声明的范围,VB.NET将强制你使用这个范围两者派生类中的getter和setter。
在基类的属性上使用ReadOnly限定符将强制所有派生类和此属性的实现也是ReadOnly。抛弃ReadOnly限定符仍然不起作用,因为您给abstract属性的任何范围都是必须应用于派生实现中的setter和getter的范围。
例如:
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
(注意setter上的私有作用域)。这不起作用,因为VB.NET坚持认为,因为你要覆盖基类属性,所以你的整个属性必须与你所覆盖的属性具有相同的范围(在这种情况下,公共)。
尝试使基类的抽象属性受到保护也不起作用,因为您需要在与基类中声明的作用域相同的级别(即受保护的)上实现该属性。通常,在不使用特定的作用域级别覆盖基类的抽象定义时,可以为getter或setter提供 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
(注意getter上的公共范围)。由于公共范围的限制性低于受保护的整体属性范围,而且不是与基类的抽象属性声明中定义的范围级别相同,因此不起作用。
如果你的课程设计正如你在问题中提到的那样,我个人会选择“java风格”的getter和setter 方法,因为它们可以用自己的方式单独声明范围界定。
答案 1 :(得分:3)
可能是一个远景......鉴于我对VB.NET的了解很少......
在C#中,您可以独立于属性指定属性访问者的可见性:
public virtual string Name
{
get { ... }
protected set { ... }
}
在此示例中,子类可以访问settor,但其他类不能。
另请注意,覆盖可以提供比覆盖更高的可见性 - 因此您可以执行此操作:
public overide string Name
{
get { ... }
public set { ... }
}
你能在VB.NET中做这样的事情吗?
答案 2 :(得分:2)
确认MrEdmuno是否正确,您可以使用Shadow。然而,看起来你不能直接遮住标记为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
答案 3 :(得分:0)
不幸的是我在这里没有视觉工作室所以我无法确认。
你有没有看过使用Shadows,这实际上和在C#属性声明中说“new”一样。
答案 4 :(得分:0)
要解决Bevan建议的问题,在VB.NET中,您可以将属性声明为具有公共getter和受保护的setter,如下所示:
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
答案 5 :(得分:0)
不要尝试覆盖该属性,因为它不是虚拟的。覆盖OnReadOnlyChanged方法并在那里处理您的业务。祝你好运
答案 6 :(得分:0)
您需要添加另一级别的层次结构;不幸的是,真正确定范围的唯一方法是使用嵌套类:
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