首页 文章

VB.NET类继承基类并实现接口问题(在C#中工作)

提问于
浏览
31

我试图在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不能处理这个问题,还是我需要在某个地方更改语法才能使其工作?

7 回答

  • 21

    您需要在基类中将属性标记为 OverridableMustOverride ,然后您可以在子类中覆盖它:

    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
    

    Edit 这是对@ M.A的回应 . 哈宁发布了 . 我们的两个解决方案都有效,但了解每个解决方案的后果非常重要 . 想象一下以下代码:

    Dim X As FooBase = New MyFoo()
    Trace.WriteLine(X.Description)
    

    什么来自X.Description?使用Overridable,您将使用Overload方法调用子类,您将获得对基类的调用 . 无论是对还是错,它对于理解宣言的后果非常重要 . 使用重载方法,您必须向上转换才能获得子项的实现:

    Trace.WriteLine(DirectCast(X, MyFoo).Description)
    

    如果您只是从子类调用MyBase.Description,那么这个问题没有实际意义,但是如果您更改了子类的定义,那么您只需要确保了解正在发生的事情 .

  • 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
    
  • 4

    VB要求实现属性声明实现 . 这是因为我实际上认为我在C#中有时会错过的一个很好的功能 - 您可以重命名实现接口成员的成员 .

    因此,如果不在 FooBase 中实现 IFoo.Description ,使这项工作的唯一方法是声明 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

    对不起,如果我迟到了,并且如果只在.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
    
  • 0

    VB.NET不支持隐式实现 . 我也遇到了这个问题并且遇到了很多麻烦 .

    当您使用生成的类(实体等)时,您必须明确声明 Implements IFoo ,这使它根本不可能 .

    因此I submitted a connection to Microsoft我希望你能投票和VB的下一版本,他们将改进编译器更聪明 .

  • 1

    由于我的代表,我无法对M.A. 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
    
  • 2

    这是一个奇怪的问题,它清楚地表明了C#和VB.NET编译器之间的区别 . 我建议你在抽象基类上实现接口,因为这会使VB.NET编译器感到高兴,并且在执行时你的子类仍然会有元数据,表明它确实实现了 IFoo .

    是否有一个特定的原因,子类必须是声明它实现接口的子类?

相关问题