我试图在VB.NET中创建一个继承基本抽象类的类,并实现一个接口。接口声明一个名为Description的字符串属性。基类包含一个名为Description的字符串属性。主类继承基类并实现接口。基类中存在Description属性可满足接口要求。这在C#中工作正常但在VB.NET中引起问题。
首先,这是一个有效的C#代码示例:
public interface IFoo
{
string Description { get; set; }
}
public abstract class FooBase
{
public string Description { get; set; }
}
public class MyFoo : FooBase, IFoo
{
}
现在这是VB.NET版本,它给出了编译器错误:
Public Interface IFoo
Property Description() As String
End Interface
Public MustInherit Class FooBase
Private _Description As String
Public Property Description() As String
Get
Return _Description
End Get
Set(ByVal value As String)
_Description = value
End Set
End Property
End Class
Public Class MyFoo
Inherits FooBase
Implements IFoo
End Class
如果我使基类(FooBase
)实现接口并将Implements IFoo.Description
添加到属性,那么一切都很好,但我不希望基类实现接口。
编译错误是:
类'MyFoo'必须为接口'IFoo'实现'Property Description()As String'。实现属性必须具有匹配的'ReadOnly'或'WriteOnly'说明符。
VB.NET可以不处理这个,或者我是否需要在某处更改语法才能使其工作?
答案 0 :(得分:21)
您需要在基类中将您的属性标记为Overridable
或MustOverride
,然后您可以在子类中覆盖它:
Public MustInherit Class FooBase
Private _Description As String
Public Overridable Property Description() As String
Get
Return _Description
End Get
Set(ByVal value As String)
_Description = value
End Set
End Property
End Class
Public Class MyFoo
Inherits FooBase
Implements IFoo
Public Overrides Property Description() As String Implements IFoo.Description
Get
Return MyBase.Description
End Get
Set(ByVal value As String)
MyBase.Description = value
End Set
End Property
End Class
修改强> 这是对@ M.A的回应。哈宁发布。我们的两个解决方案都有效,但了解每个解决方案的后果非常重要。想象一下以下代码:
Dim X As FooBase = New MyFoo()
Trace.WriteLine(X.Description)
X.Description的结果是什么?使用Overridable,您将使用Overload方法调用子类,您将获得对基类的调用。无论是对还是错,它对于理解宣言的后果非常重要。使用重载方法,您必须向上转换才能获得子实现:
Trace.WriteLine(DirectCast(X, MyFoo).Description)
如果您只是从子类调用MyBase.Description,那么这个问题没有实际意义,但是如果您更改了子类的定义,那么您只需要确保了解正在发生的事情。
答案 1 :(得分:11)
无论如何,您必须指定IFoo接口的实现细节。
这个简单的选择怎么样?
Public Class MyFoo
Inherits FooBase
Implements IFoo
Overloads Property Description() As String Implements IFoo.Description
Get
Return MyBase.Description
End Get
Set(ByVal value As String)
MyBase.Description = value
End Set
End Property
End Class
答案 2 :(得分:4)
VB要求实现属性声明实现。这是因为我实际上认为我在C#中有时会错过VB的一个很好的功能 - 你可以重命名实现接口成员的成员。
因此,在IFoo.Description
中未实现FooBase
而实现此工作的唯一方法是声明Description
Overridable
,然后将MyFoo
定义为:
Public Class MyFoo
Inherits FooBase
Implements IFoo
Public Overrides Property Description() As String Implements IFoo.Description
Get
Return MyBase.Description
End Get
Set(ByVal value As String)
MyBase.Description = value
End Set
End Property
End Class
答案 3 :(得分:3)
很抱歉,如果我迟到了,并且如果只在.NET 4中引入了此功能,也会道歉,但以下内容是可能的(现在)
Public Interface IFoo
Property Description() As String
End Interface
Public MustInherit Class FooBase
Implements IFoo
Public MustOverride Property Description As String Implements IFoo.Description
End Class
Public Class MyFoo
Inherits FooBase
Private _description As String
Public Overrides Property Description As String
Get
Return _description
End Get
Set(value As String)
_description = value
End Set
End Property
End Class
答案 4 :(得分:2)
VB.NET不支持隐式实现。 我也遇到了这个问题并且遇到了很多麻烦。
当您处理必须明确声明Implements IFoo
的生成类(实体等)时,它根本不可能。
因此I submitted a connection to Microsoft我希望你能投票和VB的下一版本,他们会改进编译器,使其更加聪明。
答案 5 :(得分:1)
我不能评论MA Hanin的答案,因为我的代表,但我会建议一个小的调整,以避免编译器有关隐藏基本方法的警告,假设您不希望或不能覆盖覆盖该属性基类。
Public Class MyFoo
Inherits FooBase
Implements IFoo
Private Property IFoo_Description() As String Implements IFoo.Description
Get
Return Me.Description
End Get
Set(ByVal value As String)
Me.Description = value
End Set
End Property
End Class
答案 6 :(得分:0)
这是一个奇怪的问题,它清楚地显示了C#和VB.NET编译器之间的区别。我建议你在抽象基类上实现接口,因为这会使VB.NET编译器感到高兴,并且在执行时你的子类仍然会有元数据,表明它实际上实现了IFoo
。
是否有一个特定的原因,子类必须是声明它实现接口的那个?