Альтернатива множественного наследования в Java - PullRequest
8 голосов
/ 24 июня 2009

Я создал две бобы

class BackPageBean{
   String backPage = null;
  :
  :
  :
}


class InformationMessageBean{
   String informationMessage = null;
  :
  :
  :
}

Теперь, если класс поддерживает бэк-страницы, он будет расширять backPageBean или, если ему нужно показать какое-то сообщение, он расширяет InformationMessageBean.

class BackPageAware extends backPageBean{
}

class InfoMessAware extends InformationMessageBean{
}



    someFunction () {
       if ( theObject instanceOf backPageBean ) {
              prepareTheBackPage ( theObject.getBackPage() );
       }

       if ( theObject instanceOf InformationMessageBean ) {
              showtheInformation ( theObject.getMessage() );
       }

   }

Теперь проблема в том, что если я хочу иметь bean-компонент, который является одновременно BackPageAware и InformationAware, тогда как у нас нет множественного наследования, каким должен быть подход?

Ответы [ 8 ]

11 голосов
/ 24 июня 2009

использовать интерфейсы:

interface InfoMessAware {

     String getMessage();
}

interface BackPageAware {

     String getBackPage();
}

class MyBean implements InfoMessAware, BackPageAware {

     String getMessage() {
         return "message";
     }

     String getBackPage() {
         return "backPage";
     }
}

затем замените instanceof стандартными вызовами методов.

9 голосов
/ 24 июня 2009

Просто чтобы уточнить мой комментарий.

Так же, как Дарт Эру говорит, что вы создаете два интерфейса и два по умолчанию Реализации. Когда у тебя есть боб который нуждается в обоих поведениях, которые вы иметь этот класс реализовать два интерфейсы, но вы также создаете переменные по умолчанию Реализации. Таким образом, вы все еще не нужно дублировать любой код.

    interface InfoMessAware {

         String getMessage();
    }

    interface BackPageAware {

         String getBackPage();
    }

class DefaultInfoMessAware {
         String getMessage() {
             return "message";
         }
}

class DefaultBackPageAware {
         String getBackPage() {
             return "backPage";
         }
}

    class MyBean implements InfoMessAware, BackPageAware {
         private InfoMessAware messAware = new DefaultInfoMessAware();
         private BackPageAware backPageAware = new DefaultBackPageAware();

         String getMessage() {
             return messAware.getMessage();
         }

         String getBackPage() {
             return backPageAware.getBackPage();
         }
    }
8 голосов
/ 24 июня 2009

Проблема, которую вы описываете, требует использования композиции, а не наследования. Класс BackPageAware означает, что он знает об этом классе / функциональности. Наследование означает, что это IS BackPage. Вы описали отношения HAS A .

Как уже много раз говорилось, используйте интерфейсы для определения контрактов на получение информации о том, что объект HAS .

1 голос
/ 21 ноября 2009

Как обсуждалось в других ответах, множественное наследование может быть смоделировано с использованием интерфейсов и композиции за счет необходимости написания большого количества стандартного кода. Однако существует ряд проектов, которые могут автоматизировать это либо во время компиляции (через препроцессор), либо во время выполнения, например jmixin .

1 голос
/ 24 июня 2009

Ваши два исходных класса должны быть интерфейсами, каждый из которых имеет метод, который извлекает информацию, которую должны возвращать реализации.

public interface BackPageBean {
   public String getBackPage();
}


public interface InformationMessageBean {
   public String getInformationMessage();   
}

Если вы хотите, чтобы класс реализовывал как BackPageBean, так и InformationMessageBean, вы просто делаете это:

public MyBean implements BackPageBean, InformationMessageBean {

  public String getBackPage() {
    return null;
  }

  public String getInformationMessage() {
    return null;
  }
}

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

0 голосов
/ 30 июля 2013

Вы можете иметь BackPageAware и InformationAware в качестве интерфейсов, а не классов. Это позволяет вам затем извлекать сообщения из обоих интерфейсов в случае, если «bean», на который вы ссылаетесь, имеет BackPageAware и InformationAware.

public class Name implements BackPageAware, InformationAware {}
0 голосов
/ 24 июня 2009

Вы не можете расширять несколько классов, но вы можете реализовать несколько интерфейсов. Помните, что когда вы применяете интерфейс к классу, объект класса имеет отношение IS-A с интерфейсом.

0 голосов
/ 24 июня 2009

Объявите BackPageAware и InformationAware как интерфейсы, создайте абстрактные классы, которые реализуют эти интерфейсы для обеспечения функциональности по умолчанию. Любой класс, который должен быть только одним из двух интерфейсов, может наследовать соответствующий абстрактный класс. Класс, который должен быть и тем, и другим, может наследовать один из абстрактных классов и реализовывать другой интерфейс или реализовывать оба интерфейса, что угодно. Если функциональности по умолчанию нет, то вам даже не нужны абстрактные классы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...