Запретить / ограничить наследование метода - PullRequest
2 голосов
/ 12 января 2012

У меня есть приложение, в котором все объекты расширяют абстрактный класс, который определяет такие методы, как create() edit() retrieve() и delete().Поскольку каждый из дочерних классов использует одну и ту же логику для этих функций, абстрактный класс определяет это поведение по умолчанию, и в тех немногих случаях, когда его необходимо дополнить, дочерние классы могут переопределять или использовать встроенные мной хуки.

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

Создание двух родительских классов, одного для изменяемых объектов и одного для неизменяемых, является уродливым и, вероятно, вызывает проблемы в будущем, связанные с обслуживанием.Я мог бы сделать так, чтобы неизменные объекты переопределяли методы-нарушители с помощью пустого метода, который ничего не делал, но это также кажется грязным и, как будто я не делаю правильный ООП в этот момент.способ позволить большому набору классов всем наследовать набор методов, но для некоторых из них не наследовать все методы?(Рассматриваемое приложение написано на php, но общие методы ООП на любом языке могут быть полезны).

Ответы [ 6 ]

3 голосов
/ 12 января 2012

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

Final, так что гарантируется, что все неизменяемые дочерние элементы не смогутредактировать или удалять

бонусы этой стратегии

  • легко проверять, является ли объект неизменным, проверяя instanceof неизменной базы

  • легко изменять объекты с неизменяемых и обратно, изменяя то, что они расширяют

2 голосов
/ 13 января 2012

На самом деле создавать классы с пустыми методами или сгенерировать ошибки - плохо - такие методы сбивают с толку, они занимают место и ничего не делают.

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

0 голосов
/ 09 сентября 2017

Начиная с PHP 5.4, вы можете использовать Черты .

Например, вы можете создать базовый класс, включающий только те методы, которые есть у всех дочерних классов:

class EntityManager {
    public function create() {/*...*/}
    public function retrieve() {/*...*/}
}

Затем вы можете определить пару признаков:

trait EditTrait {
    public function edit() {/*...*/}
}

trait DeleteTrait {
    public function delete() {/*...*/}
}

Затем вы создадите неизменный дочерний класс, подобный этому:

class LogManager extends EntityManager {
    ...
}

И изменяемый дочерний класс, подобный этому:

class ContactManager extends EntityManager {
    use EditTrait;
    use DeleteTrait;

    ...
}

Черты имеют некоторые преимущества по сравнению с некоторыми другими решениями, такими как:

  • Нет дублирования кода.
  • Единый базовый класс.
  • Методы, которые не работают или не имеют смысла, не отображаются в классах, которые их не поддерживают (особенно важно для документов и API).
0 голосов
/ 10 июня 2017

Вот супер короткий обходной путь, сделайте ваш метод окончательным и начните с:

    if(self::class!=static::class) return;#or throw an error

Это не помешает самому наследованию, но методы не будут работать в дочерних классах (с ошибкой или без - решать только вам).

0 голосов
/ 12 января 2012

Еще одна мысль, которую я хотел выбросить как возможное решение.Классы могут реализовать интерфейс, который выглядит следующим образом:

Interface Immutable {
    const immutable = true;
}

, а затем базовый абстрактный класс может записывать методы delete() и edit() с

if (!$this->immutable) {
    //do_stuff
}

хорошо распространяются на другие классификации классов, такие как NonDeletable и NonEditable, чтобы обеспечить более тонкое поведение.

0 голосов
/ 12 января 2012

Мне нравится подход Java к этому.Брось исключение.Создайте UnsupportedOperationException и для тех реализаций, которые не должны использовать определенный метод, выведите один, чтобы пользователь знал, что он не может использовать эту функциональность для этой реализации.

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