30

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() {}
}

さまざまな理由から、両方のメソッドを持つインターフェイスが必要です。

4

5 に答える 5

32

実装の多重継承は許可されていません。ただし、コンポーネントは複数のインターフェイスを継承できます。

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

于 2012-11-14T23:51:08.200 に答える
8

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

于 2012-11-14T23:54:59.313 に答える
5

インターフェイスの実装は、クラスを拡張するときの「継承」ではありません。

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

複数のものに「見える」ことは問題ありませんが、複数のものに「なる」ことはできません。


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

于 2012-11-14T23:56:25.237 に答える
1

これを試してください。Java8が必要です。

ファイルをコピーして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 opensource@{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;
                }
        }
        /************************************************************************************/

}
于 2015-01-20T13:28:39.287 に答える
0

この関連する質問で、ジェイはこれに対する答えを提供します。違いは、実装とインターフェースの指定です。

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

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

例として、多重継承を許可する対応物であるC++を見ることができます。このリンクは物事をよく説明し、いくつかのコード/画像の例を提供します。注意すべき点の1つは、関数が属するクラスを明示的にスコープする必要があるため、C++での問題を簡単に軽減できることです。

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

于 2012-11-15T00:07:55.267 に答える