【问题标题】:Inherit Class1 and implement Interface1 both in case Class1 already implements Interface1在 Class1 已经实现 Interface1 的情况下继承 Class1 并实现 Interface1
【发布时间】:2015-11-26 06:19:05
【问题描述】:

第一件事。我希望我的标题没有误导。我尽力表达出来了。

现在,请看下面的代码。案例 1 非常简单。两种情况都按预期工作。我的问题是为什么编译器允许案例 2?是否有需要的特定场景。我想不出一个。

interface IEmployee
{
    void Register(string role);
}

abstract class Employee : IEmployee
{
    public void Register(string role)
    {
        Console.WriteLine(role);
    }
}

// Case 1
class Manager : Employee
{
}

// Case 2
class Developer : Employee, IEmployee
{
}

class Test
{
    public void Test1()
    {
        IEmployee emp1 = new Manager();
        emp1.Register("manager"); // output "manager"

        IEmployee emp2 = new Developer();
        emp2.Register("developer"); // output "developer"
    }
}

【问题讨论】:

  • 当您从 Employee 继承时,您已经从 IEmployee 继承,因为 Employee 继承自 IEmployee,只需从 Employee 或 IEmployee 继承,而不是两者都继承。这是否回答了您的问题,还是您在问它为什么有效?
  • @CalebB 我已经知道你解释了什么。问题是为什么完全允许案例 2?这种设计有什么用例吗?
  • 这是允许的,因为 IEmployee 是通过 Employee 的继承实现的,它实现了所有需要的 IEmployee 成员。据我所知,没有必要这样做,因为您可以显式声明 IEmployee。?用于通过Employee继承实现Developer类中的成员。

标签: c# oop inheritance interface


【解决方案1】:

编辑

正如我所料,答案可以在 c# 规范中找到

一些标语:

13.4.5 接口实现继承

如果不显式地重新实现接口,派生类就不能以任何方式改变它从其基类继承的接口映射

13.4.6 接口重新实现

允许继承接口实现的类通过将其包含在基类列表中来重新实现接口

阅读更多以研究所有案例(可在 Visual Studio 文件夹中找到数字副本)


首先想到的是:至少允许案例 2,因为接口可以显式实现 (sample)。它原来是可用选项的一个子集
public interface IEmployee
{
    void Register(string role);
}

public abstract class Employee : IEmployee
{
    public void Register(string role)
    {
        Console.WriteLine(role);
    }
}

// Case 2
public class Developer : Employee, IEmployee
{
    // this will not work without IEmployee in declaration!
    void IEmployee.Register(string role)
    {
        Console.WriteLine("i'm developer!");
    }
}
public class Program
{
    public static void Main()
    {
        var dev = new Developer();
        dev.Register("senior"); 

        IEmployee e = dev;
        e.Register("senior");   
    }
}

程序打印:

senior
i'm developer!

第一个值来自Employee.Register

第二个值 - 来自Developer.Register


如果Developer定义为

// Case 2
public class Developer : Employee
{
    public void Register(string role)
    {
        Console.WriteLine("i'm developer!");
    }
}

同一个程序的输出是:

i'm developer!
senior

【讨论】:

  • 他们是否需要显式继承 IEmployee 才能做到这一点,而不是继承 Employee 然后如上所示?
  • 是的,如果他们在使用EmployeeIEmployee时需要Register方法的不同结果
  • @CalebB,我添加了有关该情况的更多详细信息并更新了示例
  • 如果预期来自具体类和接口的不同输出,更好的方法是 IMO 将 Employee.Register 标记为 virtualoverride 它在Developer。然后IEmployee emp2 = new Developer(); emp2.Register("developer") 会产生 I'm developer 而不是 developer
  • @nvartak,如果我设计或拥有基类,我可以使方法虚拟并在派生类中覆盖,一切都很好。但如果基类不在我的控制之下,我需要一些其他方法来更改接口映射。实际上我不记得我上次遵循这样的设计是什么时候了:[
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多