[英]Multiple inheritance on Java interfaces
我認為多重繼承在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() {}
}
由於各種原因,我需要一個具有兩種方法的接口。
接口可以擴展一個或多個其他接口。 您還可以在類中實現多個接口。 這是合法的,因為接口只是合同 - 沒有實現。 你只是簡單地定義了一個類能夠做什么的合同,而沒有說出類將如何做到這一點。
實現接口不是“繼承”,即擴展類時。
實現接口用於聲明類“看起來像”某事,而擴展類用於聲明類“是”某事。
“看起來像”多件事情是可以的,但不是“成為”多件事。
使用擴展多個接口的空接口作為將一組接口收集到單個接口中以傳達更廣泛但重用的API的方式沒有任何問題。
試試這個,它需要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 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;
}
}
/************************************************************************************/
}
在這個相關的問題中 ,傑伊提供了一個答案。 區別在於指定實現與接口。
僅當兩個函數具有相同名稱時,才會出現實現問題。 這是因為“我使用f()的實現是什么?”這個問題沒有明顯的選擇。 有多個實現。
具有相同功能名稱的兩個接口不會發生此問題,因為它不需要進行此選擇。 相反,您只需要實現自己的函數版本。
作為一個例子,我們可以看一下允許多重繼承的對應物--C ++ 。 此鏈接可以很好地解釋,並提供一些代碼/圖像示例。 需要注意的一點是,由於您需要明確地確定函數所屬的類的范圍,因此您可以輕松地緩解C ++中的問題。
但是在Java中,我們真的不必這樣做(因為只有附加到對象的方法,如果你願意的話),因此沒有一個方法來調整范圍。 我們必須引用父類的唯一選項是使用super
關鍵字,或使用static
函數。 因此,在Java中沒有明確的選擇來解決這個問題,除非對系統進行額外的更改,否則收益甚微。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.