2012-11-14 17 views
27

私は多重継承はJavaで常に違法だと思ったが、このコードはコンパイルされます。多重継承

public interface A { 
    void a(); 
} 

public interface B { 
    void b(); 
} 

public interface AB extends A, B { 
} 

なるようABとして空のインタフェースが悪い習慣と見なされましたか?空のインターフェイスを避けながら(ジェネリックまたはそれ以外の方法で)同様のものを実現する方法はありますか?

注:インターフェイスを介して複数の継承をシミュレートする方法は問いません。

public class AbImpl implements A, B { 
    public void a() {} 
    public void b() {} 
} 

さまざまな理由から、私は両方の方法があるインターフェイスが必要です。

+0

あなたの最初の例では、基本的には、第2の例に相当するショートカットを提供します。これには何も問題はありません。 –

答えて

25

の多重継承は許可されていません。コンポーネントは複数のインタフェースを継承することができます。

複数のインターフェイスを継承しても、実装する新しいメソッドシグネチャを定義するだけなので、問題はありません。伝統的に問題を引き起こしていると見なされているか、少なくとも混乱していると思われる機能の複数のコピー(例えば、diamond of death)の継承です。

+0

ありがとうございます。 – servatj

8

インターフェイスは、1つまたは複数の他のインターフェイスを拡張できます。クラス内に複数のインタフェースを実装することもできます。インタフェースは契約のみであるため、実装はありません。どのようにクラスがそれを行うかについて何も言わずに、クラスができることのためのコントラクトを定義するだけです。

4

インタフェースの実装は、継承ではなく、を拡張してクラスを拡張したものです。

インターフェイスの実装は、クラスが「何かに似ている」と宣言するために使用されますが、拡張クラスはクラスが「何か」であることを宣言するために使用されます。

複数のもののように見えるのはOKですが、複数のものにはなりません。


より幅広く再利用されたAPIを伝達するために、1組のインターフェースを1つのインターフェースに集める方法として、複数のインターフェースを拡張する空のインターフェースを持つことは何も問題ありません。

0

this related questionには、これに対する回答が記載されています。違いは、実装とインタフェースの指定です。

実装上の問題は、2つの関数の名前が同じ場合にのみ発生します。これは、「どのようなf()の実装を使用しますか」という質問には明確な選択肢がないためです。複数の実装で。

同じ機能名の2つのインターフェイスでは、この選択を行う必要がないため、この問題は発生しません。むしろ、関数の独自のバージョンをすぐに実装する必要があります。

例として、does allow multiple inheritance - C++という相手を見ることができます。このリンクは、物事をうまく説明し、いくつかのコード/画像の例を提供します。注意すべき点の1つは、関数がどのクラスに属しているかを明示的に指定する必要があるため、C++の問題を簡単に緩和できることです。

しかし、Javaでは、(実際にはオブジェクトにアタッチされているメソッドしかないので)これを行う必要はありません。その結果、呼び出しをスコープするメソッドがありません。親クラスを参照するための唯一のオプションは、superキーワードを使用するか、static関数を使用することです。その結果、Javaでこれを解決する明確な選択肢はなく、システムに追加の変更を加えずにほとんど利益を得られません。

0

はこれを試してみてください、それは、Java 8

ちょうどStateful.javaにファイルをコピーして保存が必要です。

それだけでなく、ここに提供されています: https://bitbucket.org/momomo/opensource/src/e699d8da450897b5f6cd94a5d329b3829282d1d6/src/momomo/com/Stateful/Stateful.java?at=default

/************************************************************************************************************************************** 
* Copyright(C) 2014, Mo Enterprises Inc.                        * 
* All rights reserved.                            * 
* Mo Enterprises Inc Opensource License 'MoL1'.                      * 
*                                 * 
* (1) Use of this source code, wether identical, changed or altered is allowed, for both commercial and non-commercial use.   * 
*                                 * 
* (2) This source code may be changed and altered freely to be used only within your entity/organisation, given that a notice of all * 
*  changes introduced are listed and included at the end of a copy of this exact copyright notice, including the name and date of * 
*  the entity/organization that introduced them.                     * 
*                                 * 
* (3) The redistribution or publication to the public of this source code, if changed or altered, is striclty prohibited using any * 
*  medium not owned, and/or controlled by Mo Enterprises Inc unless a written consent has been requested and recieved by   * 
*  representatives of Mo Enterprises Inc.                       * 
*                                 * 
* (4) The distribution of any work to the public derived through the use of this source code, wether identical, changed or altered, * 
*  is allowed, as long as it in full compliance of (3).                   * 
*                                 * 
* (5) Mo Enterprises Inc considers the techniques and design patterns employed in this source code as unique and making the   * 
*  redistribution of this source code with altered names, and/or a rearrangement of code as a severe breach of the copyright law * 
*  and this license. Mo Enterprises Inc reserves all rights to puruse any and all legal options.         * 
*                                 * 
* (6) All copies of this source code, wether identical, changed/altered must include this entire copyright notice, list all changes * 
*  made including the name and date of the entity/organization that introduced them, as wel as the following disclaimer:   * 
*                                 * 
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND            * 
*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED             * 
*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE               * 
*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR            * 
*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES             * 
*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;             * 
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND             * 
*  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT              * 
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS             * 
*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                 * 
*                                 * 
* Please contact us on [email protected]{at}momomo.com if you have an improvement to this source code you'd like to contribute.   * 
* We'll make sure to include your name and/or organisation as a contributor if accepted.            * 
**************************************************************************************************************************************/ 

import java.util.IdentityHashMap; 
import java.util.Map; 

/** 
* @Author Mo. Joseph 
* 
* Consider memory leakage usage. 
* None of the public methods below should be used outside of the interface extending Stateful! 
*/ 
@SuppressWarnings("unchecked") 
public interface Stateful { 
     /** 
     * @Private access only! Strict enforcement, otherwise risks for memomry leaks! 
     */ 
     static final Map<Stateful, IdentityHashMap<Class<State>, State>> STATES = new WeakIdentityHashMap<>(); 

     /** 
     * @Protected access only! Strict enforcement, otherwise risks for memomry leaks! 
     * 
     * Note, this method can not be generified! 
     * If so, then it will conflict when a class implements several Stateful interfaces. 
     */ 
     default <Y extends Stateful, T extends State<Y>> T $(Class<T> clazz) { 
       synchronized (this) { 
         IdentityHashMap<Class<State>, State> map = STATES.get(this); 
         if (map == null) { 
           STATES.put(this, map = new IdentityHashMap<>()); 
         } 

         State state = map.get(clazz); 
         if (state == null) { 
           try { 
             map.put(cast(clazz), state = clazz.newInstance()); 
           } catch (Throwable e) { 
             throw new RuntimeException(e); 
           } 
         } 
         return (T) state; 
       } 
     } 

     /** 
     * @Protected access only! Strict enforcement, otherwise risks for memomry leaks! 
     * May only be extended from within an interface that implements Stateful. 
     */ 
     static interface State<Y extends Stateful> {} 

     /** 
     * @Private 
     * Util method for casting used here. Simple casting won't work for some reason. 
     */ 
     static <T>T cast(Object obj){ 
       return (T) obj; 
     } 



     /******************************************************************************* 
     * Example code below: 
     *******************************************************************************/ 
     public static void main(String[] args) { 
       Person mo = new Person(); 
       mo.setName("Mo. Joseph"); 
       mo.setStreet("Mansion Street 1"); 
       System.out.println(mo.getName()); 
       System.out.println(mo.getStreet()); 

       Pet garfield = new Pet(); 
       garfield.setName("Garfield"); 
       System.out.println(garfield.getName()); 

       Person santa = new Person(); 
       santa.setName("Santa"); 
       santa.setStreet("North Pole Street 1"); 
       System.out.println(santa.getName()); 
       System.out.println(santa.getStreet()); 

       mo.setName("mo"); 
       System.out.println(mo.getName()); 
       System.out.println(santa.getName()); 
       System.out.println(garfield.getName()); 
       System.out.println(santa.getStreet()); 
     } 

     public static class Person implements Named, Address { 

     } 

     public static class Pet implements Named { 

     } 

     public static interface Named extends Stateful { 
       static class State implements Stateful.State<Named> { 
         private String name; 
       } 

       public default void setName(String name) { 
         $(State.class).name = name; 
       } 

       public default String getName() { 
         return $(State.class).name; 
       } 
     } 

     public static interface Address extends Stateful { 
       static class State implements Stateful.State<Address> { 
         private String street; 
       } 

       public default void setStreet(String street) { 
         $(State.class).street = street; 
       } 

       public default String getStreet() { 
         return $(State.class).street; 
       } 
     } 
     /************************************************************************************/ 

}