【问题标题】:C# Interfaces, Polymorphism and DelegatesC# 接口、多态性和委托
【发布时间】:2012-06-25 23:55:56
【问题描述】:

当我将接口和多态结合起来时,我一团糟。

假设我有以下界面:

public Interface CanSayHello
{
     String SayHello();
}

以下类:

public Class Person : CanSayHello
{
     public String SayHello() { return "Hey, I'm a person just saying hello to you";}
}

最后是重要的类:

public Class PoshPerson: Person
{
     public String SayHello() { return "Hey, I'm too posh to say hello to you";}
}

我的第一个问题是下面的代码会收集 PoshClass 或 Person Class 的方法吗?

public delegate String Collector();
event Collector CollectorEvent;
void GetMethod(CanSayHello c){CollectorEvent += c.SayHello;}

**GetMethod(new PoshPerson());**

如果它会从 Person 类中收集方法,我想我应该将 Person 的方法声明为 virtual 并重写 PoshPerson 的方法。 我真的很希望这两个方法签名是相等的。有没有可能?

【问题讨论】:

  • 您希望其中的哪一个发生?如果您希望调用PoshPerson 中的实现,为什么要避免使用virtual / override 方法?就个人而言,我会尽可能避免方法隐藏,正是因为编译时多态性不是很直观。
  • 顺便说一句,编码指南说您应该通过将 I 作为第一个字母来指示接口。
  • 应该很容易找出发生了什么?

标签: c# inheritance delegates polymorphism


【解决方案1】:

您的示例运行Person 的方法。如果您将PoshPerson 更改为PoshPerson : Person, CanSayHello(您可能认为这不会改变,因为Person : CanSayHello),它会运行PoshPerson 的方法。

我同意@millimoose 的观点:“我会尽可能避免隐藏方法,正是因为编译时多态性不是很直观。”我建议您将Person.SayHello 更改为virtual,并将PoshPerson.SayHello 更改为override。这样,无论您是否知道实例为CanSayHelloPersonPoshPerson,当前实例类型的方法都会运行。

【讨论】:

  • 此外,如果隐藏实际上是有意的,编译器将发出警告,以在 PoshPerson 的方法声明中使用 new 关键字。
【解决方案2】:

您的示例将运行 Person 的版本。请参阅此处的说明:http://msdn.microsoft.com/en-us/library/aa664593(v=vs.71).aspx。如果您在派生类中重新定义方法(编译后的 PoshPerson.SayHello 就像您使用 new 重新定义它一样),并且基类实现了一个接口,那么重新定义的方法不会改变接口映射。

如果你让 PoshPerson 重新实现接口,它会调用 PoshPerson 的 SayHello。

public class PoshPerson : Person, CanSayHello
{
    public String SayHello() { return "Hey, I'm too posh to say hello to you";}
}

或者如果你在 Person 中使 SayHello 成为虚拟,然后在 PoshPerson 中覆盖它,它将调用 PoshPerson 的 SayHello。

【讨论】:

  • “如果你有 PoshPerson 显式实现接口”这有点误导,因为你不是在谈论“显式接口实现”,而是关于重新实现接口。
【解决方案3】:

我认为你想要更多类似的东西:

public interface ITalkable
{ 
     string SayHello(); 
     string SayGoodbye();
     etc...
}

public class Person : ITalkable
{ 
     public virtual string SayHello() { return "Hey, I'm a person just saying hello to you";} 
     public virtual string SayGoodbye() { return "Hey, I'm a person just saying goodbye to you";}
} 

public class PoshPerson: Person 
{ 
     public override string SayHello() { return "Hey, I'm too posh to say hello to you";}
     public string MakePersonSayHello() { return base.SayHello(); } 

} 

【讨论】:

    猜你喜欢
    • 2021-02-20
    • 2012-07-05
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 2011-02-20
    • 2014-08-18
    • 1970-01-01
    相关资源
    最近更新 更多