【问题标题】:Can I override an interface property?我可以覆盖接口属性吗?
【发布时间】:2012-06-30 11:15:32
【问题描述】:

Shell 示例如下。基本上,我希望客户和员工实现 IPerson 的 SSN 属性。但是,我希望客户有 get 和 set(这不是问题),但我希望员工只有 get。

Public Interface IPerson
    Property SSN As String
End Interface

Public Class Client
    Implements IPerson
    Public Property SSN As String Implements AELName.IPerson.SSN
        Get
            Return _SSN
        End Get
        Set(value As String)
            _SSN = value
        End Set
    End Property
End Class

Public Class Employee
    Implements IPerson
    Public Readonly Property SSN As String Implements AELName.IPerson.SSN
        Get
            Return _SSN
        End Get
    End Property
End Class

Employee 生成错误“'SSN' 无法实现 'SSN',因为接口 'IPerson' 上没有匹配的属性”。是否有一种简单的方法可以覆盖 Employee 的 SSN 实现?

【问题讨论】:

    标签: vb.net properties interface overriding implementation


    【解决方案1】:

    您可以实现一个空的Set - 不会更新任何内容。

    Public Class Employee
        Implements IPerson
        Public Readonly Property SSN As String Implements AELName.IPerson.SSN
            Get
                Return _SSN
            End Get
            Set
                ' Make read only for Employee
            End Set
        End Property
    End Class
    

    【讨论】:

    • 当我回到它时我会试试这个,但是使用 Employee 类的任何东西都没有对 SSN 的写访问权,它只是不会在幕后设置任何东西吗?我希望如果任何未来的开发人员尝试为员工设置 SSN,它会引发错误。
    • @Curtis - 是的,这将默默地失败。但是您可以改为抛出异常。
    • 抛出异常的绝佳解决方案。
    【解决方案2】:

    我建议将接口拆分为 IReadablePerson 和 IReadWritePerson,后者继承前者。请注意,前一个接口不是IImmutablePerson,因为后一个名称将暗示该类的消费者他们不应期望其任何属性会改变;实现IReadWritePerson 的对象不会遵守这样的期望,但会遵守人应该是可读的期望。

    拆分接口的一个小麻烦是IReadWritePerson 必须在其读/写属性的声明中包含修饰符ShadowsIReadWritePerson 的实现者必须同时提供IReadablePerson 的只读实现和IReadWritePerson 的读写实现。在 C# 中,读写属性的公共实现可以自动为任何类似命名的只读、只写或读写属性生成实现,这些属性是该类实现的任何接口的一部分,但在显式声明哪个接口时正在实现时,接口的样式(只读、只写、读写)必须与实现的样式精确匹配。烦人。

    由于不能简单地将IReadableFoo 声明为只读属性,IWriteOnlyFoo 声明为只写属性,并且让IReadWriteFoo 简单地继承两者,这一事实更加令人烦恼。如果接口实现了同名的只读属性和只写属性,则这两个属性都将不可用,因为编译器将在somevariable = object.somePropertysomeObject.someProperty = someVariable 等语句中声明,使用哪个实现是“不明确的” .并不是说我可以看到任何歧义——我看不出第一个如何使用除了 getter 之外的任何东西,或者后者除了使用 setter 之外的任何东西,但编译器无法解决它。

    【讨论】:

    • @Curtis:谢谢。我添加了几段供您阅读。
    【解决方案3】:

    要回答您的标题问题“我可以覆盖接口属性”......绝对。这是一个如何执行此操作的示例。您只需将 Overridable 关键字添加到您的基本具体实现。我知道这并不能解决将属性更改为 ReadOnly 的问题,但我想我要指出的是,覆盖基类的具体接口实现是可能的。

    Module Module1
    
        Sub Main()
    
            Dim iEntity As IEntity = New MyEntity
    
            iEntity.SetMessage(iEntity)
    
            Console.WriteLine(iEntity.Message)
    
            Console.ReadKey()
    
        End Sub
    
    End Module
    
    Public Interface IEntity
    
        Property Message As String
    
        Sub SetMessage(entity As IEntity)
    
    End Interface
    
    
    Public Class MyEntity
        Inherits BaseEntity
    
        Public Overrides Property Message As String
            Get
                Return String.Format("{0}.. and overroad.", MyBase.Message)
            End Get
            Set(value As String)
                MyBase.Message = value
            End Set
        End Property
    
        Public Overrides Sub SetMessage(entity As IEntity)
    
            Me.Message = "I was set from MyEntity."
    
        End Sub
    
    End Class
    
    
    Public Class BaseEntity
        Implements IEntity
    
        Public Overridable Property Message As String Implements IEntity.Message
    
        Public Overridable Sub SetMessage(entity As IEntity) Implements IEntity.SetMessage
            Me.Message = "I was set from BaseEntity."
        End Sub
    
    End Class
    

    【讨论】: