从两个类扩展


150

我怎样才能做到这一点:

public class Main extends ListActivity , ControlMenu 

另外,我想知道这种方法是否可行,因为我已经在类中创建了菜单,即ControlMenu,并且我将在其余的活动中进行扩展。


4
您不能一次扩展两个或多个类。Java中不允许多重继承。
yogsma 2011年

Answers:


156

您只能扩展一个类。并从许多来源实现接口。

扩展多个类不可用。我能想到的唯一解决方案是不继承任何一个类,而是继承每个类的内部变量,并通过将对对象的请求重定向到您希望它们去的对象来做更多的代理。

 public class CustomActivity extends Activity {

     private AnotherClass mClass;

     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mClass = new AnotherClass(this);
     }

     //Implement each method you want to use.
     public String getInfoFromOtherClass()
     {
        return mClass.getInfoFromOtherClass();
     }
 }

这是我想出的最好的解决方案。您可以从这两个类中获得功能,并且实际上仍然只能属于一种类类型。

缺点是您无法使用演员表来适应内部类的模具。


2
您会更快:)我将我的回答作为一些抽象的例子与您的具体示例进行比较;)
Nicolas78

1
这是一个很好的选择,并在将来提供了更大的灵活性。
David Souther

1
有关更多OOP解决方案的更多信息,请参见@SCB解决方案
虚假的,2017年

我可以在这里使用更精确的示例。不确定我是否理解。
Neo42

54

为什么不使用内部类(嵌套)

class A extends B {
    private class C extends D {
        //Classes A , B , C , D accessible here 
    }
}

4
有趣的是,专家对此技术有何看法?我想深入研究它。
TechNyquist 2014年

1
约定可以吗?
托滕

2
无法让内部阶层在课堂上工作Fragment。我的活动必须扩展Fragment,这意味着我绝对需要getView(),如果它在内部类内部,它将无法正常工作,并且其中的代码需要使用from的代码ListActivity,因此我不能扩展两次,或者执行内部类在这个例子中。
Azurespot 2015年

这是扩展抽象类的最佳解决方案,其中您需要访问介入类的变量。
tak3shi

45

正如其他人所说。不,你不能。但是,尽管多年来人们多次说过您应该使用多个接口,但他们并没有真正考虑如何使用。希望这会有所帮助。

假设您拥有class Foo并且class Bar都想尝试扩展为class FooBar。当然,正如您所说,您不能:

public class FooBar extends Foo, Bar

人们已经在某种程度上了解了其原因。而是interfaces为两者编写FooBar覆盖其所有公共方法。例如

public interface FooInterface {

    public void methodA();

    public int methodB();

    //...
} 

public interface BarInterface {

    public int methodC(int i);

    //...
}

现在制作FooBar实现相关接口:

public class Foo implements FooInterface { /*...*/ }

public class Bar implements BarInterface { /*...*/ }

现在,使用class FooBar,您可以实现FooInterface和,BarInterface同时保留FooBar对象,并直接将方法直接传递给:

public class FooBar implements FooInterface, BarInterface {

    Foo myFoo;
    Bar myBar;

    // You can have the FooBar constructor require the arguments for both
    //  the Foo and the Bar constructors
    public FooBar(int x, int y, int z){
        myFoo = new Foo(x);
        myBar = new Bar(y, z);
    }

    // Or have the Foo and Bar objects passed right in
    public FooBar(Foo newFoo, Bar newBar){
        myFoo = newFoo;
        myBar = newBar;
    }

    public void methodA(){
        myFoo.methodA();
    }

    public int methodB(){
        return myFoo.methodB();
    }

    public int methodC(int i){
        return myBar.methodC(i);
    }

    //...

}

此方法的好处,是该FooBar对象适合两者的模具FooInterfaceBarInterface。这意味着这很好:

FooInterface testFoo;
testFoo = new FooBar(a, b, c);
testFoo = new Foo(a);

BarInterface testBar;
testBar = new FooBar(a, b, c);
testBar = new Bar(b, c);

希望这阐明了如何使用接口而不是多个扩展。即使我迟到了几年。


6
这是最佳答案
user3290180 '16

这是一个很好的答案,但是我发现有一些问题需要更详细地解决。首先,从两个现有的类进行扩展会遇到更多问题,并且还会遇到许多其他障碍;其次,如果接口Foo和Bar都具有相同的功能,则需要具有优先级。明确扩大班级将迫使您提前做出这些决定。仍然是一个极好的选择:) +1
懒惰的编码者,

如果我们必须“经常”创建新的类并使这些类中的每一个都实现两个接口,该怎么办?然后,我们必须在每个类中重复这些样板实现。是否有更好的方法使类“实现”两组行为?
MasterJoe2

1
@ MasterJoe2老实说,我已经有一段时间没有使用Java了(在写这个答案的那段时间,我停了下来)。我今天避免这样做的原因之一就是您提出的问题。对可能要研究的方向的直觉是编写一个实现两个接口并对其进行扩展的抽象类。但是,我不知道这是否是有效的Java,并且当您以后想对实现类进行更改时,我觉得您将遇到同样的原始问题。抱歉,我帮不上什么忙。
SCB

37

您将要使用接口。通常,由于钻石问题,多重继承是不好的:

abstract class A {
 abstract string foo();
}

class B extends A {
 string foo () { return "bar"; }
}

class C extends A  {
 string foo() {return "baz"; }
}

class D extends B, C {
 string foo() { return super.foo(); } //What do I do? Which method should I call?
}

C ++和其他人有几种解决方法,例如

string foo() { return B::foo(); }

但是Java只使用接口。

Java Trail对接口进行了很好的介绍:http : //download.oracle.com/javase/tutorial/java/concepts/interface.html 在深入研究Android API中的细微差别之前,您可能需要遵循它。


24
我从来不明白为什么钻石问题实际上是阻止多重继承的问题。如果存在相同名称的冲突方法,为什么编译器不能只是抱怨?
皮特2014年

1
对于足够智能的编译器,事实并非如此。在编译器级别解决该问题是可能的,实际上C ++做到了virtual class。这样做会给编译器和开发人员带来许多警告和警告。
David Souther

1
两个接口中相同的默认方法如何?这是java可以处理的钻石问题的另一个示例。
Lajos Meszaros

1
@MészárosLajos但是您不要super在继承的方法中调用。可以,但是您必须指定要调用的接口方法(并且必须default在接口实现中使用关键字)。一个示例是:MyIFace.super.foo()其中MyIFace是接口。如您所见,已定义要执行的接口方法,并且完全避免了Diamond问题。如果您扩展MyClass1MyClass2,则两个类都有一个foo()和调用,super.foo()则Diamond问题会引发编译器。
JDSweetBeat

您不能返回"bar""baz"方法类型为void。无论如何,很好的解释xD
xdevs23 '16

22

是的,正如其他人所写的那样,您不能在Java中进行多重继承。如果您有两个要使用代码的类,则通常只将其子类化(例如class A)。对于类B,您可以将其的重要方法抽象到一个接口上BInterface(丑陋的名字,但是您有主意),然后说Main extends A implements BInterface。在内部,您可以实例化类的对象BBInterface通过调用的相应函数来实现的所有方法B

由于您Main现在是A,但具有,因此会将“是”关系更改为“有”关系B。根据您的用例,您甚至可以通过BInterfaceA类中删除来进行显式更改,而是提供一种直接访问B对象的方法。


这是最清晰易懂的解释。请更多投票。
Algorini 2015年


6

Java不支持多重继承,但是您可以尝试实现两个或多个接口。


4

是。斯兰道是对的。Java不允许从多个类扩展。

您想要的可能是public class Main extends ListActivity implements ControlMenu。我猜您正在尝试列出清单。

希望有帮助。


3

像另一种替代方法一样,也许您可​​以将接口与方法的默认实现一起使用。当然,这取决于您要做什么。

例如,您可以创建一个抽象类和一个接口:

public abstract class FatherClass {

    abstract void methodInherit() {
        //... do something
    }
}

public interface InterfaceWithDefaultsMethods {
    default void anotherMethod() {
        //... do something
        //... maybe a method with a callable for call another function.
    }
}

因此,在那之后,您可以扩展和实现这两个类并使用这两种方法。

public class extends FatherClass implements InterfaceWithDefaultsMethods {

    void methode() {
        methodInherit();
        anotherMethod();
    }
}

希望这对您有帮助...



2

有可能的

public class ParallaxViewController<T extends View & Parallaxor> extends ParallaxController<T> implements AbsListView.OnScrollListener {

//blah
}

Parallaxor并且ParallaxController是未知的,因此我认为它们不是SDK类。所以这对我不起作用(因此此答案显示错误)。什么是ParallaxController?这是特定的依赖性吗?请详细说明
佐伊

1

java的创建者认为多重继承的问题大于收益,因此它们不包括多重继承。您可以在此处阅读有关多重继承的最大问题之一(双重钻石问题)。

两个最相似的概念是接口实现,并且包括其他类的对象作为当前类的成员。在接口中使用默认方法与多重继承几乎完全相同,但是,仅使用默认方法的接口被认为是不好的做法。


0

您不能在Java中进行多重继承。考虑使用接口:

interface I1 {}
interface I2 {}
class C implements I1, I2 {}

或内部类:

class Outer {
    class Inner1 extends Class1 {}
    class Inner2 extends Class2 {}
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.