LINUX.ORG.RU

Переопределить часть функции (возможно ли?)

 ,


0

1

Добрый день.

Например, у меня есть класс:

class A {
  public function test() {
    echo "Test";
  }
}

Например, есть унаследованный класс, в котором переопределена функция test():

class B extends A {
  public function test() {
    echo "Test";
    echo "This is test";
  }
}

Как видно, метод наполовину копирует код (вывод «Test»). Когда речь идёт об одной строке - всё нормально. А если у меня десять строк и переопределяется 4 метода? Не копировать же их - неправильно это... Может есть какой-то способ указать, что перед интерпретацией функции, сначала, нужно выполнить часть кода из «функции-родителя»?

Поясню: речь идёт о фреймворке. Там есть action'ы. И в некоторых осуществляется проверка на то, является ли пользователь админом.

Ответ на: комментарий от theNamelessOne

метод суперкласса

Да. Спасибо. Как вариант. Тоже думаю об этом.

Просто интересно, есть ли в PHP технически такое средство.

tetramin
() автор топика
Ответ на: комментарий от tetramin

Вроде что-то такое уже успели прикрутить давно ещё.
Точно лет пять назад я в это тыкался.
PHP, конечно, очень устарел с точки зрения проектирования, но не до такой степени чтобы на нём суперкласс нельзя было дёрнуть.

Goury ★★★★★
()
Ответ на: комментарий от theNamelessOne

Но нет. Мой код:

public function action_edit() {
  if (!Auth::instance()->logged_in()) {
    $this->template->content = View::factory('error');
    return;
  }
  
  // тут остальной код
  $this->template->content = View::factory('edit');
}

Вот такая конструкция будет работать. Я сократил, на сколько это было возможно для примера. Но, если в суперкласс поместить код с условным оператором и ретурном, то он вернёт нас обратно - туда, где остальной код...

Что можете посоветовать?)

tetramin
() автор топика
Ответ на: комментарий от tetramin
class A {
public function action_edit() {
  if (!Auth::instance()->logged_in()) {
    $this->template->content = View::factory('error');
    return false;
  }
  
  // тут остальной код
  $this->template->content = View::factory('edit');
}
}

class B extends A {
public function action_edit() {
    if (false !== parent::action_edit()) {
        // юзер авторизован и можем добавить еще кода
    }
}
}
kiotoze ★★★★
()

И вот я снова вижу, что люди почему-то:

1) боятся goto, который может находиться только на одном уровне.
2) НЕ боятся return посредине метода/ф-ции, где понять, куда оно возвращает, можно только в рантайме.

Ну и еще. Раз уж ты калякаешь в ООП, то обернул бы в try {...} и лови там исключения про права доступа, вместо этих вот return.

deep-purple ★★★★★
()
Ответ на: комментарий от tetramin

Но, если в суперкласс поместить код с условным оператором и ретурном, то он вернёт нас обратно - туда, где остальной код...

Ну дык логично же.

Что можете посоветовать?)

Не знаю пых, но во многих библиотеках/фреймворках для других языков это действие (т.е. «отрендерить страницу с ошибкой, если пользователь незалогинен/не имеет доступа к ресурсу») осуществляется с помощью т.н. «Middleware», которые позволяют прозрачно для самого приложения обрабатывать и отфильтровывать http-запросы в соответствии с какой-либо логикой. См. middleware (rack) или plugins (connect).

theNamelessOne ★★★★★
()
Ответ на: комментарий от deep-purple

НЕ боятся return посредине метода/ф-ции, где понять, куда оно возвращает, можно только в рантайме.

Куда? В вызывающую функцию.

theNamelessOne ★★★★★
()

речь идёт о фреймворке

Так тем более — лыжи то едут, а продолжение ты знаешь. Оборачивайся в try-catch и лови исключения.

deep-purple ★★★★★
()
Ответ на: комментарий от theNamelessOne

В вызывающую функцию

Которых может быть несколько разных и в разных местах проекта, или мы вызывали это все через рефлекшн. Ай красота!

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

В вызывающую функцию

Которых может быть несколько разных и в разных местах проекта, или мы вызывали это все через рефлекшн. Ай красота!

Ну это да, согласен. Но при чём тут тогда «return посередине метода»? Ты не можешь знать, куда будет возвращать функция, даже если return будет в конце функции, в начале, либо если функция будет возвращать при выходе из её скопа.

theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

Ни при чем, просто к слову.

Но вот смотри. В примере киотозы идет типа перегрузка метода парента, где сам метод всеравно вызывается, возвращает а-ля статус, а потомковый пользуется этим статусом. Это же швах.

deep-purple ★★★★★
()

И в некоторых осуществляется проверка на то, является ли пользователь админом.

Я бы захерачил эту проверку в ядро фрейммворка, например.

NeverLoved ★★★★★
()
Ответ на: комментарий от theNamelessOne

Я тоже, в самом первом своем сообщении. А про ретурны-готы это вообще оффтоп был.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

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

NeverLoved ★★★★★
()
Ответ на: комментарий от deep-purple

Сделал функцию is_admin(). В ней редирект на страницу логина. Добавил в каждый метод, где требовалась проверка. Исключения - это хорошо, но не пушкой ли по воробъям? Вообще, я пока плохо умею исключения. Обязательно исправлюсь!)

tetramin
() автор топика

Странно, в нормальной динамике это элементарно делается

Io:

A := Object clone do(
  test := method("Test" println)
)

B := A clone do(
  test := method(resend; "This is a Test" println)
)

А тут целый консилиум собрался.

callbackhell
()
Ответ на: комментарий от tetramin

Исправляйся быстрее. Исключения — это правильный путь.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Один раз добавил провеку в класс, от которого наследуются контроллеры vs проверка в каждом action'e, как у ТС. Ну да, те же яйцы.

NeverLoved ★★★★★
()
Ответ на: комментарий от tetramin

Что можете посоветовать?)

Что мешает тебе сделать в суперклассе:

public function action_edit() {
  if (!Auth::instance()->logged_in()) {
    $this->template->content = View::factory('error');
    return;
  }
  $this->at_action_edit_exit();
}

protected function at_action_edit_exit() {}

В субклассе доопределить это как тебе надо.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Уродливое, нерасширяемое, негибкое решение. Если мне нужн будет, чтобы в дочернем классе была action-edit, котрая выполняет

at_action_edit_exit1();
at_action_edit_exit2();
мне придется переписывать класс. А если понадобится, чтобы в дочерних классах где-то было at_action_edit_exit1(), а где-то at_action_edit_exit2(), а где-то вместе, становиться еще печальней. Ты показал хардкор, который сродни неуклюжести функционального подхода.

callbackhell
()
Ответ на: комментарий от callbackhell

Если мне нужн будет

Вот когда будет нужен, тогда и приходи.

Странно, в нормальной динамике это элементарно делается

Тебе странно, потому что ты не понял вопроса.

no-such-file ★★★★★
()

man OOP, trait, SOLID, YAGNI, DRY

anonymous
()
Ответ на: комментарий от no-such-file

тогда и приходи

Чтобы запилить неуклюжую обертку над неуклюжим говном? Не, такое программирование нам не нужно.

потому что ты не понял вопроса.

А может наоборот, ты не понял ответа

callbackhell
()
Ответ на: комментарий от no-such-file

не я уверен, что ты нулевой, и просто ННП. Это была типа, вежливость.

callbackhell
()
Ответ на: комментарий от handles

какую cms лучше выбрать что бы не морочиться с кодом так как вы?

apofigez
()
Ответ на: комментарий от ThisNameWasFree

Всё нормально! Вопрос ещё не решён. Я, конечно, сделал у себя по-другому, но мне всё равно интересно, возможно ли это в PHP.

tetramin
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.