【问题标题】:Achieving multiple inheritance via interface通过接口实现多重继承
【发布时间】:2011-10-07 23:02:50
【问题描述】:

我是界面概念的初学者。

当我浏览有关“通过接口实现多重继承”的信息时,我遇到了这个链接..Multiple inheritance

我和那个项目学生有同样的疑问。

嗨,很好的解释非常有帮助在 java 的 uml 图中 鸟和马与动物没有联系,为什么?是吗 必须在派生类中使用实现相同的方法 以及为什么

void birdNoise(); 
void horseNoise(); 

为什么在 Peagus 类中

public void horseNoise()
{
    System.out.println("Horse Noise!");
}

public void birdNoise()
{ 
    System.out.println("Bird Noise!");
} 

为什么它必须在那里?为什么“记住,我们必须为接口中的每个方法编写每个类自己的实现。原因?感谢这个很好的解释谢谢

在那篇文章中,他们在 c++ 中使用了多重继承,并在 java 中转换为接口。

1.我想到的继承是在父类中有一些方法,当其他类也需要相同的方法时,这些类将继承父类并使用它。 但是在接口概念中,如果每个派生类都必须定义自己的实现,那么继承它有什么用呢?

2.如果我们必须提供自己的实现,那么为什么不在派生类本身中定义该方法。继承它有什么用?

请有人解释一下。

提前致谢。

【问题讨论】:

  • 您在这里有 3 个不同的答案,几乎都说同样的事情,这也是一个很常见的问题,您可以用谷歌搜索。如果你还不明白为什么,那要么是因为你问错了问题,要么是你没有对得到的答案给予足够的重视。

标签: java interface multiple-inheritance


【解决方案1】:

当我从 c++ 切换到 java 时,我也有同样的感觉,但现在我已经使用 java 有一段时间了,这一切都是有道理的。

1.我对继承的想法是在父级中有一些方法 类,以及在其他类中需要相同方法时 也一样,那么这些类将继承父类并使用它。

就像原作者所做的那样,您仍然可以在 java 中进行多重继承,您只需要使用接口即可。接口就像 c++ 中的纯虚拟类。

但在接口概念中,如果每个派生类都必须定义其 自己的实现那么继承有什么用呢?

在 java 中实现接口的原因是为了保证类具有这些方法。这样你就可以让一个特定的类实现一个泛型接口,然后对实现该泛型接口的每个特定类都一视同仁。

Java 设计与 c++ 设计有点不同,但是在完成了几个 java 程序之后,您将变得像使用多重继承一样擅长使用多个接口。

【讨论】:

  • 我刚要按接听键,但你比我早一秒就回答了,反正你的解释比我好一点。很好的答案。
  • @Grammin 作为初学者,我无法理解您对继承方法有自己定义的解释。我的疑问是我们为什么不在派生类本身中定义该方法。为什么要在这里引入接口概念。你能再解释一下吗?抱歉再次询问。
  • @EAGER_STUDENT 很好的主要原因之一是避免由于两个继承类具有相同的函数名而引起的命名冲突。
【解决方案2】:

每个子类都必须定义自己的实现,因为每个子类执行的操作可能略有不同。考虑以下示例:

public interface animal {
    //All implementers must define this method
    void speak();
}

此界面规定任何动物都必须有说话的方式。基本上,任何类型的动物都会发出声音。然后,我们创建了 2 个子类或 2 种不同类型的动物。

public class Dog implements animal {
    //Define how a Dog speaks
    public void speak() {
        System.out.println( "woof" );
    }
}

然后我们定义另一种动物,猫

public class Cat implements animal {
    //Define how a Cat speaks
    public void speak() {
        System.out.println( "meow" );
    }
}

在本例中,Cat 和 Dog 都是动物,因此由于我们的界面必须能够说话。但是,每个人都知道猫和狗会发出不同的声音。通过允许每个子类定义它“说话”的方式,我们可以在调用 speak() 方法时赋予 Dog 和 Cat 各自的声音,同时确保它们都是 Animals。

更具体地回答您的问题,继承强制它的子类具有特定的方法。换句话说,接口声明“我的所有子类都将定义这些方法中的每一个”。这允许我们编写代码来处理接口中的方法,而无需知道具体的子类。我们可以安全地这样做,因为我们知道每个子类都必须在接口类中定义方法。如果只有使用该方法的子类定义了它,那么我们将无法确定在所有子类上调用该方法是否安全。

请注意:如果您不希望子类定义方法,则可以像这样简单地定义一个空方法:

public class MuteAnimal implements animal {
    //A MuteAnimal can't speak!
    public void speak() { }
}

【讨论】:

  • "public class Dog extends animal" 这里的 animal 是一个接口,所以 "public class Dog implements animal" 可能会出现。
  • 是的,我意识到我不小心使用了扩展而不是工具。我已经在我的答案中修复了它,因为你必须实现一个接口
  • 我的第二个问题仍未解决。你能解释一下吗?
  • 如果您愿意,也可以让每个子类自己定义方法。然而,接口之所以有用,是因为它强制每个子类定义相同的方法。假设您要遍历一组 Animals 并调用 currAnimal.speak()。如果 Animal 是一个强制每个子类定义一个 speak() 方法的接口,那么你保证你的调用是合法的。否则,实现你的 Animal 类的人(不一定是 Animal 的作者)可能没有定义 speak(),所以你的迭代器突然抛出 missingMethod 异常。
  • 是的!非常感谢。再次阅读您的答案后,我现在明白了。老实说,错误在我这边。你的答案是绝对清楚的。但我只是这次更专注地阅读。
【解决方案3】:

如果没有多态性,继承通常是无用的。仅仅用几句话来解释这一切真的很不容易。我的建议是查看定义行为的接口(类似于 can-do 关系)以及 is-a 关系的具体继承。

正如您所了解的,一切的核心是单一职责原则。这意味着一个班级有一个责任,如果你有更多的责任,你就分开班级。

如果你举个例子,即使是飞马也不是 100% 同时是马和鸟。它将继承马,但实现鸟类的特定特征,这些特征将在接口中定义,例如 Flyable。你可以说鸟类有一种共同的飞行方式,所以从Bird那里继承它们。 Pegasus 有点不同,因此可以在使用 Fly 方法实现 Flyable 接口后定义自定义逻辑。 此外,horseNoise 和 birdNoise 的示例有点不切实际,您需要一种方法 speak() ,它会由于内部类算法执行某些操作。如果那只飞马会说话呢?每个单词都有一个方法吗?

回到 Flyable 示例,假设您现在有一个视频游戏。现在您可以对此进行多态性:假设在游戏中发生地震。你想让每一种能飞的动物都去飞。您目前在游戏中有一组动物,因此您可以这样写:

foreach(Flyable flyableAnimal in animals)
    flyableAnimal.Fly();

你只是依赖多态性......

这些只是一些随机的想法,您可以在网上找到更好的示例,希望对您有所帮助...

【讨论】:

    【解决方案4】:

    如果类 A 继承自类 B,这实际上意味着两件事:

    1. A 类可以隐式使用 B 类的所有方法和属性,并且只需要定义实际上是 A 类独有的功能。
    2. 需要 B 类型对象的代码将接受 A 类型对象。

    继承的这两个特征在某种意义上是正交的;可以想象在没有另一个的情况下其中任何一个都可能有用的地方。尽管派生类只能有一个父类,它们可以从中获得对方法和属性的隐式访问,但它们可以定义任意数量的可替代的接口。

    请注意,虽然有些人坚持认为接口形成“has-a”而不是“is-a”关系,但我认为最好将它们理解为“is __able”或“is a __er”,关键是接口不只是定义能力,而是根据能力定义可替代性(即“是一个”)。

    【讨论】:

      猜你喜欢
      • 2019-03-06
      • 1970-01-01
      • 2012-11-12
      • 2011-11-21
      • 1970-01-01
      • 2015-08-03
      • 2013-10-22
      • 2019-03-21
      • 1970-01-01
      相关资源
      最近更新 更多