it-swarm.com.de

Mehrfachvererbung auf Java-Schnittstellen

Ich dachte, Mehrfachvererbung sei in Java immer illegal, aber dieser Code wird kompiliert:

public interface A {
  void a();
}

public interface B {
  void b();
}

public interface AB extends A, B {
}

Wäre eine leere Schnittstelle wie AB eine schlechte Praxis? Gibt es eine Möglichkeit, etwas Ähnliches zu erreichen, während die leere Schnittstelle (mit Generika oder auf andere Weise) vermieden wird?

Hinweis: Ich frage nicht, wie Sie die Mehrfachvererbung über Schnittstellen simulieren können. Mir ist klar, dass ich folgendes tun könnte:

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

Aus verschiedenen Gründen brauche ich eine Schnittstelle, die beide Methoden hat.

28
Jacob Wallace

Mehrfachvererbung von Implementierungen ist nicht zulässig. Komponenten können jedoch mehrere Schnittstellen erben.

Die Vererbung mehrerer Schnittstellen ist nicht problematisch, da Sie einfach neue Methodensignaturen definieren, die implementiert werden sollen. Es ist die Vererbung mehrerer Funktionskopien, die traditionell als problematisch oder zumindest als Verwirrung angesehen wird (z. B. der Diamant des Todes ).

27
Brian Agnew

Eine Schnittstelle kann eine oder mehrere andere Schnittstellen erweitern. Sie können auch mehrere Schnittstellen in Ihren Klassen implementieren. Es ist legal, weil die Schnittstelle nur Vertrag ist - es gibt keine Implementierung. Sie definieren einfach einen Vertrag für das, was eine Klasse tun kann, ohne etwas darüber zu sagen, wie die Klasse dies tun wird.

8
Maciej Ziarko

Das Implementieren von Schnittstellen ist keine "Vererbung", wenn Sie eine Klasse erweitern .

Das Implementieren von Schnittstellen wird verwendet, um zu deklarieren, dass eine Klasse wie etwas aussieht, während das Erweitern von Klassen verwendet wird, um zu deklarieren, dass eine Klasse etwas ist.

Es ist in Ordnung, wie mehrere Dinge "auszusehen", aber nicht wie mehrere Dinge "zu sein".


Es ist nichts Falsches daran, leere Schnittstellen zu haben, die mehrere Schnittstellen erweitern, um eine Reihe von Schnittstellen zu einer einzigen Schnittstelle zusammenzufassen und eine umfassendere, aber wiederverwendete API zu vermitteln.

4
Bohemian

In dieser verwandten Frage gibt Jay eine Antwort darauf. Der Unterschied besteht darin, die Implementierung gegenüber der Schnittstelle anzugeben. 

Das Problem bei der Implementierung tritt nur auf, wenn zwei Funktionen denselben Namen haben. Dies liegt daran, dass es keine offensichtliche Wahl für die Frage gibt "Welche Implementierung von f() verwende ich?" mit mehreren Implementierungen.

Das Problem tritt nicht bei zwei Schnittstellen mit demselben Funktionsnamen auf, da diese Auswahl nicht erforderlich ist. Sie müssen lediglich eine eigene Version der vorliegenden Funktion implementieren. 

Als Beispiel können wir ein Gegenstück betrachten, das die Mehrfachvererbung zulässt - C++ . Dieser Link erklärt die Dinge gut und enthält einige Code/Image-Beispiele. Beachten Sie Folgendes: Da Sie explizit festlegen müssen, zu welcher Klasse eine Funktion ohnehin gehört, können Sie das Problem in C++ leicht abmildern.

In Java müssen wir dies jedoch nie tun (da es nur Methoden gibt, die an Objekte angehängt sind, wenn Sie so wollen). Als Ergebnis haben Sie keine Methode, um den Aufruf zu definieren. Die einzigen Optionen, die wir auf eine übergeordnete Klasse verweisen müssen, sind das Schlüsselwort super oder die Funktion static. Infolgedessen gibt es keine eindeutige Möglichkeit, dieses Problem in Java zu lösen, ohne dass zusätzliche Änderungen am System vorgenommen werden müssen.

0
Doug Swain

Versuchen Sie dies, es erfordert Java 8. 

Kopieren Sie die Datei und speichern Sie sie in Stateful.Java. 

Es ist auch hier verfügbar: https://bitbucket.org/momomo/opensource/src/e699d8da450897b5f6cd94a5d329b3829282d1d6/src/momomo/com/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;
                }
        }
        /************************************************************************************/

}
0
momomo