Как избавится от дублирования кода?

Сразу код:
class CommonClass {
  public function foo() {/*...*/}
  public function bar() {/*...*/}
}

class ConcreteClass1 extends CommonClass {
  public function doSomething1() {/*...*/}
  public function doSomething2() {/*...*/}
}

class ConcreteClass2  {
  public function doSomething1() {/* тот же код из ConcreteClass1 */}
  public function doSomething2() {/* тот же код из ConcreteClass1 */}
  public function doSomething3() {/*...*/}
}


В реализации ConcreteClass2 присутсвуют два метода, которые полностью дублируют код методов из ConcreteClass1. При этом наследоваться от ConcreteClass1 нельзя, потому в ConcreteClass2 методы foo() и bar() из CommonClass не должны быть.
Как можно избавиться от дублирования без множественного наследования и трейтов?
  • Вопрос задан
  • 1236 просмотров
Пригласить эксперта
Ответы на вопрос 7
max-kuznetsov
@max-kuznetsov
Главный IT-архитектор
Я бы создал класс AbstractClass, чтобы CommonClass и ConcreteClass1 наследовались от него. ConcreteClass2 должен наследоваться от ConcreteClass1. В AbstractClass вынес бы из CommonClass те члены, которые должны быть общими для всех классов. Всё.
Ответ написан
Комментировать
Denormalization
@Denormalization
Никак, либо наследование, либо трейты.
Самый оптимальный вариант трейты.
Ответ написан
Finesse
@Finesse
Может, так:

common.php:
public function doSomething1() {/*...*/}
public function doSomething2() {/*...*/}


index.php:
class CommonClass {
  public function foo() {/*...*/}
  public function bar() {/*...*/}
}

class ConcreteClass1 extends CommonClass {
  include "common.php";
}

class ConcreteClass2  {
  include "common.php";
  public function doSomething3() {/*...*/}
}
Ответ написан
Комментировать
Vityarik
@Vityarik
Обычно делегирование дает больше гибкости чем наследование

class CommonClass {
  public function foo() {/*...*/}
  public function bar() {/*...*/}
}

class ConcreteClass1 extends CommonClass {
  public function doSomething1() {/*...*/}
  public function doSomething2() {/*...*/}
}

class ConcreteClass2  {
  ConcreteClass1 concreteClass1 = new ConcreteClass1();
  public function doSomething1() {concreteClass1.doSomething1()}
  public function doSomething2() {concreteClass1.doSomething2()}
  public function doSomething3() {/*...*/}
}


Попробуйте рассмотреть шаблон Стратегия.
Ответ написан
Комментировать
angry_cellophane
@angry_cellophane
Поддерживаю идею с делегированием. Еще бы разнести логику по разным интерфейсам
interface Common {
        void foo();
        void bar();
    }

    interface ConcreteWithSomething {
        void doSomething1();
        void doSomething2();
    }

    interface Concrete1 extends Common, ConcreteWithSomething {}

    interface Concrete2 extends ConcreteWithSomething {
        void doSomething3();
    }

    class Concrete2Impl implements Concrete2  {
        @Inject private Concrete1 delegate;

        public void doSomething1() { delegate.doSomething1(); }
        public void doSomething2() { delegate.doSomething2(); }
        public void doSomething3() {/*...*/}
    }
Ответ написан
Комментировать
abler98
@abler98
Software Engineer
Можно просто переопределить методы foo и bar в ConcreteClass2
Ответ написан
Комментировать
He11ion
@He11ion
PHP-monkey
потому в ConcreteClass2 методы foo() и bar() из CommonClass не должны быть.

Это почему это не должны? Вариант два - либо доопределить в ConcreteClass1 public function foo() { return null; }
или в ConcreteClass2 что-то вроде
public function doSomething1() { 
$cl = new ConcreteClass1(); 
return $cl->doSomething1();
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы