覆盖子类中的 ReadOnly 属性以使其读/写(VB.NET 或 C#)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/554369/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Overriding ReadOnly Property in a subclass to make it Read/Write (VB.NET or C#)
提问by Rob Sobers
This doesn't seem possible in VB.NET with properties since the property statement itself must describe whether it is ReadOnly
or not.
这在带有属性的 VB.NET 中似乎是不可能的,因为属性语句本身必须描述它是否ReadOnly
存在。
In my example below, it doesn't let me make the ReadWriteChild
compile. I guess I could make the parent Read/Write, and then have the ReadOnlyChild's setter not do anything, but that seems sort of hacky. The best alternative seems to be abandoning properties in favor of getter/setter methods in this case.
在我下面的示例中,它不允许我进行ReadWriteChild
编译。我想我可以让父级读/写,然后让 ReadOnlyChild 的 setter 不做任何事情,但这似乎有点麻烦。在这种情况下,最好的选择似乎是放弃属性以支持 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
采纳答案by CraigTP
Given what you're trying to accomplish, and with the sample code you posted, VB.NET will not let you do this.
考虑到您要完成的任务以及您发布的示例代码,VB.NET 不会让您这样做。
Ordinarily, you can declare a property in VB.NET like so:
通常,您可以像这样在 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
Basically marking the overall property as public, but giving a more restrictive scope to the setter (or getter).
基本上将整个属性标记为 public,但为 setter(或 getter)提供了更严格的范围。
The main problem in your case is the MustInherit (i.e. abstract) base class. Since the property you're defining in there is marked as MustOverride, you can't provide a default implementation (i.e. it, too, is abstract), and this includes the "Get" and "Set" outlines, therefore, whichever "overall" scope you give to this abstract property declaration, VB.NET will force you to use this scope for boththe getters and setters within derived classes.
您的情况的主要问题是 MustInherit(即抽象)基类。由于您在其中定义的属性被标记为 MustOverride,因此您无法提供默认实现(即它也是抽象的),并且这包括“Get”和“Set”大纲,因此,无论“整体“你给这个抽象的财产申报范围,VB.NET将强制您使用此范围内为双方的getter和派生类中的setter方法。
Having the ReadOnly qualifier on the base class's property will force all derived classes and the implementations of this property to also be ReadOnly. Leaving off the ReadOnly qualifier still will not work, since whatever scope you give to the abstract property will be the scope you must apply to both the setters and getters within derived implementations.
在基类的属性上使用 ReadOnly 限定符将强制所有派生类和此属性的实现也为 ReadOnly。离开 ReadOnly 限定符仍然不起作用,因为无论您赋予抽象属性的范围是您必须应用于派生实现中的 setter 和 getter 的范围。
For example:
例如:
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
(Note the Private scoping on the setter). This will not work as VB.NET is insisting that since you're overriding the base classes property, your entire property must have the same scope as the property you're overriding (in this case, public).
(注意 setter 上的 Private 范围)。这不会起作用,因为 VB.NET 坚持认为,由于您要覆盖基类属性,因此您的整个属性必须与您要覆盖的属性(在本例中为公共)具有相同的范围。
Attempting to make the base class's abstract property protected will not work either, since you would then be required to implement the property at the same level of scoping as it's declared in your base class (i.e. protected). Ordinarily, when not overriding a base class's abstract definition with a specific scoping level, you can give a getter or setter a morerestrictive scoping level, but you can't give it a lessrestrictive scoping level.
尝试使基类的抽象属性受保护也不会起作用,因为您将需要在与基类中声明的范围相同的范围内实现该属性(即受保护)。通常,当不使用特定范围级别覆盖基类的抽象定义时,您可以为 getter 或 setter 提供更严格的范围级别,但不能为其提供更宽松的范围级别。
Therefore:
所以:
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
(Note the public scoping on the getter). Doesn't work either due to the public scope being less restrictive than the overall property scope of protected, and moreover, not of the same scoping level as defined on the base class's abstract property declaration.
(注意 getter 上的公共范围)。不起作用,因为公共范围比受保护的整体属性范围的限制更少,而且与基类的抽象属性声明中定义的范围级别不同。
If the design of your classes is as you mention in your question, I personally, would go with a "java-style" getter and setter methodsas they can then be declared separately with their own scoping levels.
如果您的类的设计与您在问题中提到的一样,我个人会使用“java 风格”的 getter 和 setter方法,因为它们可以使用自己的范围级别单独声明。
回答by Bevan
Might be a longshot ... given that my knowledge of VB.NET is minimal ...
可能是一个长期目标......鉴于我对 VB.NET 的了解很少......
In C# you can specify the visibility of a property accessor independently of the property:
在 C# 中,您可以独立于属性指定属性访问器的可见性:
public virtual string Name
{
get { ... }
protected set { ... }
}
In this example, child classes can access the settor, but other classes cannot.
在这个例子中,子类可以访问 settor,但其他类不能。
Also note that overrides can have greater visibility than what they override - so you can do this:
另请注意,覆盖可以比它们覆盖的内容具有更大的可见性 - 因此您可以这样做:
public overide string Name
{
get { ... }
public set { ... }
}
Could you do something like this in VB.NET ?
你能在 VB.NET 中做这样的事情吗?
回答by MrEdmundo
Unfortunatly I haven't got visual studio on here so I can't confirm.
不幸的是,我这里没有视觉工作室,所以我无法确认。
Have you looked at using Shadows, this is effectivly the same as saying "new" in C# property declaration.
您是否看过使用 Shadows,这实际上与在 C# 属性声明中说“new”相同。
回答by spacemonkeys
Confirm that MrEdmuno is correct in that you can use Shadow. However it appears you can't directly shadow something that is marked MustInherit, so you need to inherit into a class (Parent 2) ... then into your readonly (actually thinking about it you probably don't need to use shadows if you inherit into a class)
确认 MrEdmuno 是正确的,因为您可以使用 Shadow。但是看起来你不能直接隐藏标记为 MustInherit 的东西,所以你需要继承到一个类(父 2)......然后进入你的只读(实际上考虑它你可能不需要使用阴影,如果你继承到一个类中)
I think my comment question still stands, why are you needing to do this ? If they are your own classes would you be better to modify those, or implement as a interface ?
我认为我的评论问题仍然存在,你为什么需要这样做?如果它们是你自己的类,你会更好地修改它们,还是作为接口实现?
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
回答by Mark
To address what Bevan suggested, in VB.NET you can declare a property as having a public getter and a protected setter, as follows:
为了解决 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
回答by Emmanuel Romulus
Do not try to override the property since it is not virtual. Override the OnReadOnlyChanged methods and handle your business there. Good luck
不要尝试覆盖该属性,因为它不是虚拟的。覆盖 OnReadOnlyChanged 方法并在那里处理您的业务。祝你好运
回答by supercat
You need to add another level of hierarchy; unfortunately, the only way to really scope things properly is to use nested classes:
您需要添加另一个层次结构;不幸的是,真正正确确定范围的唯一方法是使用嵌套类:
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