我正在阅读“ Java教程”(第2次)。我刚读完有关接口的部分,但仍然不了解Java接口如何模拟多重继承。有比书中更清楚的解释吗?
我正在阅读“ Java教程”(第2次)。我刚读完有关接口的部分,但仍然不了解Java接口如何模拟多重继承。有比书中更清楚的解释吗?
Answers:
假设您的域中有两种东西:卡车和厨房
卡车具有driveTo()方法,而Kitchens具有cook()方法。
现在,假设Pauli决定从送货卡车的后面出售比萨饼。他想要一种可以与drive()和cook()一起使用的东西。
在C ++中,他将使用多重继承来做到这一点。
在Java中,这被认为太危险了,因此您可以从主类继承,但是可以从接口“继承”行为,这些行为对于所有意图和目的都是抽象类,没有字段或方法实现。
因此,在Java中,我们倾向于使用委托来实现多重继承:
Pauli对卡车进行了子类化,并在一个名为厨房的成员变量中为卡车添加了厨房。他通过调用kitchen.cook()来实现Kitchen接口。
class PizzaTruck extends Truck implements Kitchen {
Kitchen kitchen;
public void cook(Food foodItem) {
kitchen.cook(foodItem);
}
}
他是一个快乐的人,因为他现在可以做类似的事情;
pizzaTruck.driveTo(beach);
pizzaTruck.cook(pizzaWithExtraAnchovies);
好的,这个愚蠢的故事是要指出它不是多重继承的模拟,它是真正的多重继承,附带条件是您只能继承协定,只能从称为接口的空抽象基类继承。
public void cook()
Kitchen和PizzaTruck都将实现的Cookery接口(带有)。
default
。接口仍然没有实例状态,但是它们确实具有类可以继承的方法。
您可能会感到困惑,因为您会在本地查看多个继承,就一个类而言,它是从多个父级继承实现细节的。在Java中这是不可能的(并且在可能的情况下经常导致语言滥用)。
接口允许类型的多重继承,例如aclass Waterfowl extends Bird implements Swimmer
可以被其他类当作aBird
和如同a一样使用Swimmer
。这是多重继承的更深层含义:允许一个对象像它一次一样属于多个不相关的不同类。
这是通过Java接口实现多重继承的方法。
要实现什么?
类A扩展了B,C // //在Java中这不可能直接实现,但是可以间接实现。
class B{
public void getValueB(){}
}
class C{
public void getValueC(){}
}
interface cInterface{
public getValueC();
}
class cChild extends C implemets cInterface{
public getValueC(){
// implementation goes here, call the super class's getValueC();
}
}
// Below code is **like** class A extends B, C
class A extends B implements cInterface{
cInterface child = new cChild();
child.getValueC();
}
给定下面的两个接口...
interface I1 {
abstract void test(int i);
}
interface I2 {
abstract void test(String s);
}
我们可以使用下面的代码来实现这两个...
public class MultInterfaces implements I1, I2 {
public void test(int i) {
System.out.println("In MultInterfaces.I1.test");
}
public void test(String s) {
System.out.println("In MultInterfaces.I2.test");
}
public static void main(String[] a) {
MultInterfaces t = new MultInterfaces();
t.test(42);
t.test("Hello");
}
}
我们不能扩展两个对象,但是我们可以实现两个接口。
接口不模拟多重继承。Java创建者认为多重继承是错误的,因此Java中没有这样的事情。
如果要将两个类的功能组合为一个,请使用对象组合。即
public class Main {
private Component1 component1 = new Component1();
private Component2 component2 = new Component2();
}
如果要公开某些方法,请定义它们并将它们委托给相应的控制器。
这里的接口可能会派上用场-如果Component1
实现接口Interface1
和Component2
工具Interface2
,则可以定义
class Main implements Interface1, Interface2
这样您就可以在上下文允许的地方互换使用对象。
很简单 您可以在一种类型中实现多个接口。因此,例如,您可能有一个实现,List
它也是的一个实例Deque
(而Java确实... LinkedList
)。
您只是不能从多个父级继承实现(即扩展多个类)。 声明(方法签名)没有问题。
您知道什么,从一个JavaScript开发人员试图了解这些东西到底发生了什么的角度出发,我想指出几点,如果有人愿意,请告诉我我在这里缺少的内容偏离标记。
接口真的很简单。愚蠢地,疯狂地简单。它们像人们最初想象的那样愚蠢,疯狂,这就是为什么在这个确切的主题上存在如此多重复的问题的原因,因为人们试图使它们的使用量超出实际,从而使人们不清楚使用它们的一个原因。在我接触过的每个Java服务器端代码库中,普遍存在滥用。
那么,为什么要使用它们呢?大多数时候你不会。您当然不希望像许多人所想的那样一直使用它们。但是,在我问您何时选择之前,让我们先谈谈它们不是什么。
接口不是:
乍一看,它们真的很简单。人们总是愚蠢地滥用,所以很难理解重点是什么。这只是验证/测试。一旦编写了一些符合接口并可以工作的东西,删除该“实现”代码就不会破坏任何东西。
但是,如果您正确使用了接口,则不希望将其删除,因为在那里拥有接口可以为下一个开发人员提供工具,为他们希望继续应用程序其余部分的另一组数据库或Web服务编写访问层。使用,因为他们知道自己的课程将失败,直到他们获得100%的“按预期完成”界面。所有接口的作用都是验证您的类并确定您实际上已经实现了您承诺的接口。而已。
它们也是便携式的。通过公开您的接口定义,您可以为希望使用未公开代码的人们提供一组遵循的方法,以便他们的对象正确使用它。他们不必实现接口。他们可以将它们记在一张记事本纸上,然后仔细检查。但是,有了该接口,您将更有保证,直到它具有适当版本的接口后,您才能尝试工作。
那么,任何接口都不可能实现一次以上?完全没用。多重继承?停止伸手去拿那彩虹。Java首先避免了它们的出现,无论如何,复合/聚合对象在许多方面都更加灵活。并不是说接口不能以多重继承允许的方式帮助您建模,但实际上它不是任何形式或形式的继承,因此不应被视为如此。这只是保证您的代码在实现实现的所有方法之前不会起作用。
Y
应该也可以接受对a的引用X
。如果无法进行这种替换,那么这种关系有什么用?
这不是多重继承的模拟。在Java中,您不能从两个类继承,但是如果实现两个接口,“看来您是从两个不同的类继承的”,因为您可以将您的类用作两个接口中的任何一个。
例如
interface MyFirstInteface{
void method1();
}
interface MySecondInteface{
void method2();
}
class MyClass implements MyFirstInteface, MySecondInteface{
public void method1(){
//Method 1
}
public void method2(){
//Method 2
}
public static void main(String... args){
MyFirstInterface mfi = new MyClass();
MySecondInterface msi = new MyClass();
}
}
这将起作用,并且您可以使用mfi和msi,这看起来像是多重继承,但这不是因为您不继承任何东西,而是重写接口提供的公共方法。
您需要精确:
Java允许接口的多重继承,但只允许实现的单一继承。
您可以像这样在Java中对接口进行多重继承:
public interface Foo
{
String getX();
}
public interface Bar
{
String getY();
}
public class MultipleInterfaces implements Foo, Bar
{
private Foo foo;
private Bar bar;
public MultipleInterfaces(Foo foo, Bar bar)
{
this.foo = foo;
this.bar = bar;
}
public String getX() { return this.foo.getX(); }
public String getY() { return this.bar.getY(); }
}
顺便说一句,Java之所以没有实现完全多重继承,是因为它会产生歧义。假设您可以说“ A扩展了B,C”,那么B和C都具有函数“ void f(int)”。A继承哪个实现?使用Java的方法,您可以实现任意数量的接口,但是接口仅声明一个签名。因此,如果两个接口都包含具有相同签名的函数,那很好,您的类必须实现具有该签名的函数。如果您继承的接口的功能具有不同的签名,则这些功能彼此无关,因此没有冲突的问题。
我并不是说这是唯一的方法。C ++通过建立优先实现规则来实现真正的多重继承。但是Java的作者决定消除歧义。我是不知道是因为出于哲学考虑,认为这样做是为了编写更清晰的代码,还是因为他们不想做所有额外的工作,所以不知道。
说接口“模拟”多重继承是不公平的。
当然,您的类型可以实现多个接口,并且可以多态地充当许多不同的类型。但是,您显然不会在这种安排下继承行为或实现。
通常在您可能需要多重继承的地方查看合成。
或实现类似多重继承的潜在解决方案是Mixin接口-http: //csis.pace.edu/~bergin/patterns/multipleinheritance.html。小心使用!
如果它们自己实现接口,则实际上您可以从多个具体类中“继承”。innerclasses
帮助您实现以下目标:
interface IBird {
public void layEgg();
}
interface IMammal {
public void giveMilk();
}
class Bird implements IBird{
public void layEgg() {
System.out.println("Laying eggs...");
}
}
class Mammal implements IMammal {
public void giveMilk() {
System.out.println("Giving milk...");
}
}
class Platypus implements IMammal, IBird {
private class LayingEggAnimal extends Bird {}
private class GivingMilkAnimal extends Mammal {}
private LayingEggAnimal layingEggAnimal = new LayingEggAnimal();
private GivingMilkAnimal givingMilkAnimal = new GivingMilkAnimal();
@Override
public void layEgg() {
layingEggAnimal.layEgg();
}
@Override
public void giveMilk() {
givingMilkAnimal.giveMilk();
}
}
我想指出一些令人毛骨悚然的东西,它们来自C ++,您也可以轻松继承许多实现。
具有许多方法的“宽”接口意味着您必须在具体的类中实现许多方法,并且不能在实现之间轻松共享这些方法。
例如:
interface Herbivore {
void munch(Vegetable v);
};
interface Carnivore {
void devour(Prey p);
}
interface AllEater : public Herbivore, Carnivore { };
class Fox implements AllEater {
...
};
class Bear implements AllEater {
...
};
在此示例中,Fox和Bear不能为其接口方法munch
和共享相同的基本实现devour
。
如果基本实现看起来像这样,我们可能想将它们用于Fox
和Bear
:
class ForestHerbivore implements Herbivore
void munch(Vegetable v) { ... }
};
class ForestCarnivore implements Carnivore
void devour(Prey p) { ... }
};
但是我们不能继承这两个。基本实现需要是类中的成员变量,并且定义的方法可以转发给该成员变量。即:
class Fox implements AllEater {
private ForestHerbivore m_herbivore;
private ForestCarnivore m_carnivore;
void munch(Vegetable v) { m_herbivore.munch(v); }
void devour(Prey p) { m_carnivore.devour(p); }
}
如果接口增长(即超过5-10种方法...),这将变得笨拙。
更好的方法是将接口定义为接口的集合:
interface AllEater {
Herbivore asHerbivore();
Carnivore asCarnivore();
}
这意味着Fox
并且Bear
仅必须实现这两种方法,并且接口和基类可以独立于AllEater
涉及实现类的聚合接口而增长。
如果适用于您的应用程序,则可以减少这种方式的耦合。
Java中确实没有模拟多重继承的功能。
人们有时会说您可以使用接口来模拟多重继承,因为您可以为每个类实现多个接口,然后在类中使用合成(而不是继承)来实现您试图继承的多个类的行为。首先。
在某些情况下,多重继承变得非常方便,并且在不编写更多代码的情况下很难用接口替换。例如,某些Android应用程序在同一应用程序中使用从Activity派生的类以及从FragmentActivity派生的类。如果您要在公共类中共享某个特定功能,则在Java中,您将必须复制代码,而不是让Activity和FragmentsActivity的子类从同一SharedFeature类派生。Java中泛型的糟糕实现也无济于事,因为编写以下内容是非法的:
public class SharedFeature<T> extends <T extends Activity>
...
...
Java不支持多重继承。
这个使用接口支持多重继承的故事是我们开发人员编写的。接口提供了比具体类更大的灵活性,并且我们可以选择使用单个类来实现多个接口。根据协议,这是我们遵循的两个创建类的蓝图。
这正试图接近多重继承。我们要做的是实现多个接口,这里我们不扩展(继承)任何东西。实现类是将添加属性和行为的类。它不能使实现脱离父类。我会简单地说,在Java中不支持多重继承。
不,Java不支持多重继承。既不使用类也不使用接口。请参阅此链接以获取更多信息 https://devsuyed.wordpress.com/2016/07/21/does-java-support-multiple-inheritance
我还必须说Java不支持多重继承。
您必须在Java中区分extends
和implements
关键字之间的含义。如果使用extends
,则实际上是在该关键字之后继承该类。但是,为了使一切变得简单,我们不能使用extends
多次。但是,您可以根据需要实现任意数量的接口。
如果实现一个接口,那么您错失每个接口中所有方法的实现的可能性为零(例外:Java 8中引入的接口方法的默认实现)因此,您现在已经完全了解事情的发生了您已经融入了新鲜的课堂。
实际上,为什么Java不允许多重继承,多重继承使代码有些复杂。有时,父类的两个方法可能由于具有相同的签名而发生冲突。但是,如果您被迫手动实施所有方法,您将对发生的事情有全面的了解,就像我上面提到的那样。它使您的代码更易于理解。
如果您需要有关Java接口的更多信息,请查看本文http://www.geek-programmer.com/introduction-to-java-interfaces/
在两个Java类之间不能直接进行多重继承。在这种情况下,java建议使用接口来声明接口内的方法,并使用Child类实现方法。
interface ParentOne{
public String parentOneFunction();
}
interface ParentTwo{
public String parentTwoFunction();
}
class Child implements ParentOne,ParentTwo{
@Override
public String parentOneFunction() {
return "Parent One Finction";
}
@Override
public String parentTwoFunction() {
return "Parent Two Function";
}
public String childFunction(){
return "Child Function";
}
}
public class MultipleInheritanceClass {
public static void main(String[] args) {
Child ch = new Child();
System.out.println(ch.parentOneFunction());
System.out.println(ch.parentTwoFunction());
System.out.println(ch.childFunction());
}
}