두 클래스에서 확장


150

어떻게해야합니까 :

public class Main extends ListActivity , ControlMenu 

또한이 접근법은 클래스의 메뉴를 ControlMenu로 만들고 나머지 활동으로 확장하고 있음을 알고 싶습니다.


4
한 번에 두 개 이상의 수업을 확장 할 수 없습니다. Java에서는 다중 상속이 허용되지 않습니다.
yogsma

답변:


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
당신은 더
빨랐습니다 :)

1
이것은 매우 훌륭한 대안이며 앞으로 훨씬 더 많은 유연성을 제공합니다.
David Souther

1
더 많은 OOP 솔루션에 대해서는 @SCB 솔루션을 참조하십시오
idish

더 정확한 예를 여기서 사용할 수 있습니다. 잘 모르겠습니다.
Neo42

54

내부 클래스를 사용하지 않는 이유 (Nesting)

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

4
intersting approach, 전문가들은이 기술에 대해 어떻게 생각합니까? 나는 그것을 파고 싶다.
TechNyquist

1
컨벤션도 괜찮습니까?
12

2
에서 내부 클래스를 사용할 수 없습니다 Fragment. 내 활동이 반드시 확장되어야합니다. Fragment즉, 절대적으로 필요 getView()합니다. 내부 클래스 내부에 있으면 작동하지 않으며 코드를 사용해야하는 곳이 있으므로 코드를 ListActivity두 번 확장 할 수 없습니다. 또는 내부 클래스를 수행하십시오. 이 예에서.
Azurespot

이는 임 포징 클래스의 변수에 액세스해야하는 추상 클래스를 확장하기위한 최상의 솔루션입니다.
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);

    //...
}

그리고 지금 확인 Foo하고 Bar상대적 인터페이스를 구현 :

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

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

자, 함께 class FooBar, 당신은 모두를 구현할 수 FooInterfaceBarInterface유지하면서 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객체가 FooInterface와 의 금형에 모두 맞는다는 것 BarInterface입니다. 이것은 이것이 완벽하게 괜찮다는 것을 의미합니다.

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

이것은 매우 좋은 대답이지만 더 자세히 다루어야 할 몇 가지 문제가 있습니다. 먼저 두 개의 기존 클래스에서 확장하는 것은 약간 더 문제가 될 것이고 통과해야 할 추가 장애물이있을 것입니다. 두 번째는 인터페이스 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는 인터페이스 만 사용합니다.

: 자바 산책로 인터페이스에 큰 소개가 http://download.oracle.com/javase/tutorial/java/concepts/interface.html을 당신은 아마 따르도록 할 것을 그 안드로이드 API의 뉘앙스로 다이빙을하기 전에.


24
나는 왜 다이아몬드 문제가 실제로 다중 상속을 방해하는 문제인지 이해하지 못했습니다. 이름이 같은 충돌하는 메소드가있는 경우 컴파일러가 단지 불평 할 수없는 이유는 무엇입니까?
pete

1
충분히 지능적인 컴파일러의 경우 그렇지 않습니다. 컴파일러 수준에서 해결하는 것이 가능하며 실제로 C ++은로 수행합니다 virtual class. 그렇게 할 때 컴파일러와 개발자 모두에게 많은 경고와 경고가 있습니다.
David Souther

1
두 개의 인터페이스에서 동일한 기본 방법은 어떻습니까? 그것은 자바가 다룰 수있는 다이아몬드 문제의 또 다른 예입니다.
Lajos Meszaros

1
@ MészárosLajos 그러나 super메소드 상속에서 호출하지는 않습니다 . 글쎄, 할 수는 있지만 호출 할 인터페이스 메소드를 지정해야합니다 ( default인터페이스 구현에서 키워드 를 사용해야합니다 ) . 예를 들면 다음과 같습니다. MyIFace.super.foo()여기서 MyIFace는 인터페이스입니다. 보시다시피 실행할 인터페이스 방법이 정의되어 있으며 다이아몬드 문제를 완전히 피합니다. 당신이 확장하는 경우 MyClass1MyClass2, 두 클래스는이 foo(), 그리고 호출은 super.foo()다음 컴파일러는 다이아몬드 문제가 발생합니다.
JDSweetBeat

"bar"또는의 "baz"메소드 유형을 반환 할 수 없습니다 void. 어쨌든, 좋은 설명 xD
xdevs23

22

그러나 다른 사람들이 쓴 것처럼 Java에서는 다중 상속을 수행 할 수 없습니다. 코드를 사용하려는 클래스가 두 개인 경우 일반적으로 클래스를 하나만 하위 클래스 화 A합니다. class의 B경우 중요한 메소드를 인터페이스 BInterface(추악한 이름이지만 아이디어를 얻음)에 추상화 한 다음 말합니다.Main extends A implements BInterface . 내부에서 클래스의 객체를 인스턴스화하고 의 해당 함수를 호출하여 B모든 메소드를 구현할 수 있습니다 .BInterfaceB

이렇게하면 "is-a"관계가 "has-a"관계로 변경됩니다. Main현재는 A이지만 B. 유스 케이스에 따라 클래스 BInterface에서 를 제거하여 변경 사항을 명시 적으로 지정 A하고 대신 B 객체에 직접 액세스하는 방법을 제공 할 수도 있습니다.


이것은 가장 읽기 쉽고 이해하기 쉬운 설명입니다. 더 찬성 투표하십시오.
Algorini


6

Java는 다중 상속을 지원하지 않지만 둘 이상의 인터페이스를 구현할 수 있습니다.


4

예. slandau가 옳다. 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 - 클래스없는 가정, 그래서 알 수 있습니다. 그래서 이것은 나를 위해 작동하지 않습니다 (따라서이 답변은 오류를 보여줍니다). 시차 컨트롤러 란 무엇입니까? 이것이 특정한 의존성입니까? 자세히 설명하십시오
Zoe

1

Java 작성자는 다중 상속 문제가 이점보다 중요하다고 판단하여 다중 상속을 포함하지 않았습니다. 당신은 다중 상속의 가장 큰 문제 중 하나 (이중 다이아몬드 문제)에 대해 읽을 수 있습니다 여기에 .

가장 유사한 두 가지 개념은 인터페이스 구현이며 다른 클래스의 객체를 현재 클래스의 멤버로 포함합니다. 인터페이스에서 기본 메소드를 사용하는 것은 다중 상속과 거의 동일하지만 기본 메소드만으로 인터페이스를 사용하는 것은 좋지 않습니다.


0

당신은 자바에서 다중 상속을 할 수 없습니다. 인터페이스 사용을 고려하십시오.

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

또는 내부 수업 :

class Outer {
    class Inner1 extends Class1 {}
    class Inner2 extends Class2 {}
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.