2010-10-12 1 views
1

Я работаю с определенной библиотекой API в Java. Он имеет базовый класс A, а также B и C, которые оба расширяют A. B & C обеспечивают аналогичную, но отличную функциональность, все три класса находятся в библиотеке.Как реализовать множественную наследование в Java

public abstract class A 
{ 
    virtual foo(); 
} 

public class B extends A {} 
public class C extends A {} 

Как получить элементы A, B и C в моем классе? Если я использую интерфейсы для реализации классов, существует много дублированного кода, и внутренние классы не позволят мне переопределять существующие методы, чтобы сохранились вызывающие интерфейсы A, B и C.

Как реализовать множественную наследование в Java?

EDIT: Благодарим за редактирование. Джордж, теперь более понятный, забыл упомянуть одно критическое требование: мои классы должны иметь A в качестве базы, чтобы управлять ими с помощью API платформы.

+6

поэтому в чем вопрос? – aioobe

+0

@Hemang, см. Оригинальную неотредактированную версию этого вопроса. – Pops

+0

Поскольку у вас уже есть Google, вы можете знать, что java и многие другие языки удалили множественное наследование. Если вы можете быть более конкретным, почему в вашем случае вы должны иметь его, может быть предложена лучшая альтернатива – Hemang

ответ

0

Похоже, вы хотите расширить A - назовите его D - переопределите его foo(), а затем добавьте новые подклассы E & F, которые расширяют D и добавляют их собственные функции.

Вы можете подумать об извлечении общих интерфейсов и повторном использовании их. Хорошая среда IDE с возможностью рефакторинга упростит работу.

14

Напомним, у вас есть:

class A 
{ 
    public void foo() {} 
} 

class B extends A 
{ 
    public specificAMethod() {} 
} 

class C extends A 
{ 
    public specificCMethod() {} 
} 

Вышеуказанные классы в библиотеке, что вы не можете получить доступ или изменить. Вы хотите получить поведение как B и C в третьем классе D, как если бы это было возможно написать:

class D extends B, C 
{ 
} 

Правильно?

Как насчет использования B и C вместо наследования? Вам действительно нужно наследование? Вы хотите называть частные методы B и C?

class D 
{ 

private B b; 
private C c; 
} 
+4

предпочитают композицию над наследованием! –

+1

@ Билл вы читали «первые образцы дизайна головы»? :) Я сделал. – vulkanino

+0

Это то же самое, что и у делегации – Saideira

0

Множество наследований классов невозможно на Java, однако вы можете использовать множественное наследование для интерфейсов. Используя Delegation pattern, вы можете комбинировать поведение нескольких других классов в одном.

+1

Да, я могу использовать делегирование, но мне нужно написать много кода клея, поскольку классы имеют много методов. – Saideira

+0

По большей части IDE может сгенерировать его для вас или использовать динамический прокси. См. Например, http://java.sys-con.com/node/37748 –

+0

@Saideria, если у вас слишком большие классы? Если ваш интерфейс пересылает много вещей, мне интересно, можете ли вы что-то сделать неправильно. Например, у вас могут быть сеттеры и геттеры - в общем, попробуйте устранить их и поместить код, который вызвал их в вашем классе. Может ли ваш класс сделать больше, чем одну простую вещь? Возможно, он должен быть разбит на несколько классов ... Это то, что не имеет правильного ответа, но старайтесь делать такие вещи неоднократно, каждый раз, когда вы смотрите на любой код. В конечном итоге это стоит того. –

2

Если вы возьмете общий подход «Предпочитаете состав над наследством», вы можете обнаружить, что один или оба класса не должны быть фактически «унаследованы» в любом случае. В обоих случаях классы имеют строгие отношения «есть-а»? Если вы можете сказать «Has-a» вслух, и это звучит глупо, вам, вероятно, нужна композиция.

Например, если вы используете колоду карт, то 3 пики - это 3, и это - лопата, но вы также можете думать об этом, как и о ней, - 3, и у нее есть костюм (лопата). Поскольку вы можете думать об этом таким образом, вам, вероятно, следует предпочесть интерпретацию и использование композиции.

Постарайтесь держаться подальше от деревьев наследования более чем на несколько объектов в глубину - и если вы когда-нибудь почувствуете желание использовать множественное наследование, попробуйте обойти его. Это один из тех случаев, когда Java-тип заставляет вас разрабатывать ваш код, чтобы он был немного читабельнее, не предоставляя функцию (но, по общему признанию, когда вы действительно этого хотите, ее нет и это может повредить! Некоторый уровень mixin будет хороший).

0

Совершенно другой подход применяется в COM: все объекты наследуют от IUnknown, который имеет метод, который может быть переведен на Java, как:

Object queryInterface(Class<?> clazz) 

Простейшая реализация этого метода может быть:

if(clazz.isAssignableFrom(this.getClass())) 
    return this; 
else 
    return null; 

Где одиночное наследование не будет работать, это достаточно просто добавить:

else if(class == SomeClass.class) { 
    return something; 
} else ... 

Таким образом, можно решить даже самые сложные случаи множественного наследования, и вы получите полный контроль над тем, что возвращается и когда, так что вы избегаете многих проблем с «классическим» множественным наследованием от таких языков, как C++, например, проблемой fork-join.

0

С Java 1.8 вы можете использовать интерфейсы со стандартными методами. Это очень удобно, и я часто использую его. Covariant return types также поддерживаются. Существуют ограничения fiew (см. Ниже), но вам не нужно реализовывать наследование самостоятельно и позволить компилятору работать на вас.

public interface A { 
    default A foo() { 
     return this; 
    } 
} 

public interface B extends A { 
    @Override 
    default B foo() { 
     return this; 
    } 
} 

public interface C extends A { 
    @Override 
    default C foo() { 
     return this; 
    } 
} 

public interface D extends B, C { 
    @Override 
    // if the return type does not implement B and C 
    // the comiler will throw an error here 
    default D foo() { 
     return this; 
    } 
} 

Обратите внимание, что это, но обратите внимание, что вы не можете назвать super.foo или определить поля или частных пользователей (до Java 9), так как его еще интерфейсов. Если вы согласитесь с этими ограничениями, это откроет вам новый уровень объектно-ориентированного программирования.

 Смежные вопросы

  • Нет связанных вопросов^_^