2008-12-09 3 views
7

У меня есть интерфейс A, для которого я должен предоставить несколько различных реализаций . Однако эти реализации используют некоторые вспомогательные методы, поэтому Я переместил эти методы в абстрактный базовый класс.Что (не) объявить при реализации интерфейса с абстрактным классом?

Interface A { 
    void doX(); 
} 

abstract Class B implements A { 
    protected void commonY() { 
     // ... 
    } 

    @Override 
    public abstract void doX(); 
} 

Class C extends B { 
    @Override 
    public void doX() { 
     // ... 
    } 
} 

Class D extends B { 
    @Override 
    public void doX() { 
     // ... 
    } 
} 

Мой код работает, как ожидалось, но у меня есть несколько вопросов:

  • Должен ли я объявить абстрактный метод DOX() в классе B? Почему нет)?

  • Должен ли я также явно объявлять «реализует A» в классах C и D? Почему нет)?

ответ

8

Я думаю, что было бы лучше сделать это следующим образом:

Interface A { 
     void doX(); 
} 

abstract Class B { 
     protected void commonY() { 
       // ... 
     } 
} 

Class C extends B implements A{ 

     public void doX() { 
       // ... 
     } 
} 

Class D extends B implements A{ 

     public void doX() { 
       // ... 
     } 
} 

Не следует смешивать интерфейс (подпись методов) с реализацией.

+0

Преимущество этого решения в том, что, когда класс X, реализующий Z, но который требует функциональности метода commonY, вводится, он может специализировать класс B. – 2008-12-09 11:59:03

4
  • Должен ли я объявить абстрактный метод DOX() в классе B? Почему нет)?

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

  • Должен ли я также явно объявлять «реализует A» на классах C и D? Почему нет)?

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

0

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

Наследование транзитивно. Вам не нужно писать, что класс C реализует интерфейс A, если класс C выводит класс B, который реализует интерфейс A. Однако для него также не так много вреда.

+0

Я не думаю, что абстрактный класс должен реализовывать каждый метод в интерфейсе. Я только что протестировал это, и кажется, что вы можете реализовать интерфейс в абстрактном классе, фактически не объявляя ни одного из методов интерфейса. – 2008-12-09 11:48:44

+0

Хм, ты, наверное, прав. Я ушел с моей памяти о Java и моем текущем опыте в C#. В C# абстрактный класс, реализующий интерфейс, требуется для реализации всех интерфейсных методов (даже просто помечая их абстрактными). – yfeldblum 2008-12-09 12:16:06

0

я бы не объявить doX() в B и не добавить «implements A» на C и D, потому что вы должны not repeat yourself.

Реферат doX() в B ничего не добавляет, как это уже указано «implements A». То же самое верно для добавления «implements A» на C и D.

Единственное возможное использование этих положений будет документация: Если вы хотите сделать это очень четко указано, что C (или D) является разновидностью A, то вы можете добавить implements, но вы должны знать, что это действительно Безразлично Не имеет значения для компилятора.

1

Я просто поставлю другой вариант.

Включить абстрактный класс B в класс AUtil, который не реализует A. Для сигнатур метода может потребоваться дополнительный аргумент типа A для работы.

C и D реализуют A и создают экземпляр AUtil внутри. Это позволяет C и D расширять другие классы.

1

Я согласен с JeeBee: рассмотрите возможность реализации ваших вспомогательных методов где-то, кроме абстрактного базового класса.

Если ваш вспомогательный метод commonY() существует только в абстрактном базовом классе B, все классы, реализующие интерфейс A, должны также расширить базовый класс B, чтобы воспользоваться этой реализацией commonY(). Но вы не всегда можете быть вынуждены продлить класс B.

Также, если вы хотите изменить реализацию commonY() в будущем? Затем вы затронете множество реализаций интерфейса A. Но если вы не контролируете все эти реализации интерфейса A, вы можете повлиять на их функциональность (плохой), не намереваясь.

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

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

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