2012-11-14 80 views
27

我认为多重继承一直非法在Java中,但是这个代码编译:具有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

你的第一个例子中提供了一个快捷方式,基本上等同于第二个例子。这样做没有任何问题。 –

回答

25

实现的多重继承是不允许的。不过,组件可以继承多个接口。

继承多个接口没有问题,因为您只是定义要实现的新方法签名。这是传统上被视为造成问题的多个功能副本的继承,或者至少是混淆(例如,diamond of death)。

+0

感谢提及deat的diamon;) – servatj

8

接口可以扩展一个或多个其他接口。你也可以在你的类中实现多个接口。这是合法的,因为接口只是合同 - 没有实现。你只是简单地定义一个班级能够做什么的合同,而无需说明班级将如何做。

4

实现接口不是“继承”,也就是当你将扩展为的一个类。

实现接口用于声明一个类“看起来像”某事,而扩展类用于声明某个类是“某事”。

可以“看起来像”多个东西,但不是“是”多个东西。


使用扩展多个接口的空接口作为将一组接口收集到单个接口以传达更广泛但可重用的API的方式没有任何问题。

0

this related question,周杰伦提供了一个答案。区别在于指定实现与接口。

仅当两个函数具有相同的名称时才会出现实现问题。这是因为对于“我使用什么f()的实现”这个问题没有明显的选择。“有多个实现。

该问题不会发生在具有相同函数名称的两个接口上,因为它不需要进行此选择。相反,你只需要实现你自己的版本就可以了。

作为一个例子,我们可以看一下does allow multiple inheritance - C++的对应物。这个链接很好地解释了一些事情,并提供了一些代码/图像示例有一点需要注意的是,由于你需要明确地规定一个函数所属的类,你可以很容易地用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; 
       } 
     } 
     /************************************************************************************/ 

}