【问题标题】:C# Multiple Interface InheritanceC# 多接口继承
【发布时间】:2014-03-11 23:33:00
【问题描述】:

给定以下代码:

interface IParent
{
    void ParentPrintMethod();
}

interface IChild : IParent
{ 
    void ChildPrintMethod();
}

class Baby : IChild
{
    public void ParentPrintMethod()
    {
       Console.WriteLine("Parent Print Method");
    }

    public void ChildPrintMethod()
    {
       Console.WriteLine("Child Print Method");
    }

}

此时一切都很好。如果您要创建 Baby 类的新实例,如下所示,

Baby x = new Baby();

一切正常,您可以访问 ParentPrintMethod() 和 ChildPrintMethod();

但是,有人可以向我解释一下如果您执行以下操作会发生什么吗?

IParent x = new Baby();

在这种情况下,您可以访问 ChildPrintMethod() 吗?执行此操作时究竟发生了什么?

【问题讨论】:

  • 我正在测试它,但是我不明白为什么会发生这种情况。在我看来,好像跳过了一个继承级别,我想知道这是否是这样的。
  • 也许你应该描述一下你的实验和让你吃惊的部分?
  • 请以 I...IParent、IChild、ICanHasCheeseburger 等开头命名您的接口。
  • 我知道命名约定,我只是在这个例子中跳过了它。
  • +1。感谢您的编辑。以您想要的方式命名类/对象是您个人的选择(您在之前的评论中已明确说明)。不幸的是,大多数人没有无限的时间来查看问题——所以如果你的代码看起来很奇怪/与标题不匹配,你可能会得到关于风格而不是真实答案的 cmets。请注意,几乎每个人都将部分答案花在了您不寻常的界面命名选择上——同样的努力也可以花在更好地回答您的问题上。

标签: c# oop inheritance multiple-inheritance


【解决方案1】:

然后您指定您只对Parent 声明的Interface 感兴趣,因此您只能访问Parent 中声明的那些方法,即使对象本身的实例有更多可用。

【讨论】:

  • 所以本质上排除了类中定义的其他方法?
  • 不排除他们。他们还在那里。您只是无权访问它们,因为您已指定您只对接口 Parent 声明的方法感兴趣。
  • 这样想。如果你对某人说你想要一辆车,他们可能会给你一辆 2 门、4 门、掀背车、敞篷车等。你不知道是什么样的车,但你知道它可以像汽车一样工作.所以当你说你想要一个Parent对象时,它可以做什么ELSE并不重要,只要它可以做Parent定义的任何事情。
  • 好的,包括在内,但无法访问。谢谢
  • 不,只是未知。它将像婴儿一样使用它的记忆和功能,并且像 (Baby)x 一样可施放
【解决方案2】:

不,你不会。变量x,作为Parent 类型(按惯例,接口通常以I 开头)只能看到Parent 接口中定义的方法。期间。

【讨论】:

  • 太好了,谢谢。那么是否跳过了继承级别? (因为缺乏更好的术语)
  • 你在声明中跳过了一个级别,是的。这完全取决于您想做什么,是否有用。
  • 当你实现接口时,你并没有继承任何东西。这是您同意执行的合同。继承意味着子继承父对象定义的行为。这就是接口正在发生的事情。
【解决方案3】:

您对该对象的引用将像 Parent 接口的实例一样,并且无法访问 Child 方法。

【讨论】:

    【解决方案4】:

    这听起来很不正常,但是:所有Children 都是Parents,但并非所有Parents 都是Children。

    Parent 访问 Childs 方法是没有意义的,因为如果父母不是孩子,这将是一个错误。

    仍然可以访问您给出的示例中的子方法,但您必须首先将x 转换为Child((Child)x).ChildPrintMethod()。这是合理的,因为如果 x 不是有效的 Child,则在发生强制转换时会引发异常,而不是尝试运行该方法。

    您可以提前测试这是否可行,而不必使用if (x is Child) 捕获异常

    编辑:

    要将变量当作子变量一样重用,您可以像这样创建对它的本地引用:

    if (x is Child) {
        Child y = (Child)x;
        ...
    }
    

    【讨论】:

    • 好点,谢谢。你怎么能做一个更“永久”的演员?
    • 你可以说Child y = (Child)x,或者x as Child。后者的不同之处在于它返回null,如果它不是一个孩子,而不是抛出一个异常。
    • Child y = x as Child;,导致 y 是有效的 Child 或 null 否则。 (运营商as基于is,可以在这里阅读更详细的内容:blogs.msdn.com/b/ericlippert/archive/2010/09/16/…
    【解决方案5】:

    没有“跳过继承”之类的东西。您的对象只是“通过”它的一个接口查看,有效地隐藏了该接口中未声明的任何其他内容。它没有魔法。

    【讨论】:

    • 好点,这解释了 ((Child)x).ChildPrintMethod() 仍然能够调用 ChildPrintMethod,谢谢
    猜你喜欢
    • 2017-09-11
    • 1970-01-01
    • 2018-04-30
    • 2013-11-25
    • 2022-08-12
    • 2011-03-24
    • 1970-01-01
    • 2023-03-14
    相关资源
    最近更新 更多