2012-02-29 6 views
2

Я разрабатываю приложение Yii. И мне интересно, можно ли объявить в модели поведение своего рода «абстрактного» метода. Я знаю, что это невозможно использовать непосредственно после объявления:«Абстрактные» методы в Yii Поведение

abstract class FantasticBehavior extends CActiveRecordBehavior 
{ 
    public abstract function doSomethingFantastic(); 
} 

, потому что нам нужна установка этого класса. Но также я знаю, что Yii является полной магией :)

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

Извините, если я пропустил что-то сказать или что-то неясно. Просто спроси, и я попытаюсь объяснить, что я имею в виду.

Кто-нибудь знает об этом?

Заранее спасибо.

UPD

Я понимаю, что Yii только PHP. Он не расширяет PHP. Это надстройка над ней. И он не имеет множественного наследования, поскольку PHP не делает этого.

Я действительно понимаю, что метод поведения не может быть объявлен с использованием абстрактного ключевого слова. Вот почему я написал слово «абстрактный» в кавычках. Но что угодно. Я знаю, как работают действия.

Вопрос был, если я могу как-то обязать модель (например, дочерний элемент CActiveRecord) объявить какой-либо метод.

Например, для моих целей, я могу сделать что-то вроде этого:

class FantasticBehavior extends CActiveRecordBehavior 
{ 
    public function doFantasticThings() 
    { 
     $this->owner->prepareForFantastic(); 
     // some code 
    } 
} 

Поэтому, если я придаю такое поведение моей модели и методы вызова doFantasticThings этот метод будет пытаться вызвать метод prepareForFantastic от модели (владелец). И если у модели нет метода prepareForFantastic, объявленное новое исключение будет выбрано, потому что вызывается не объявленный метод.

Похоже, я сам ответил на свой вопрос :) Что вы думаете об этом?

UPD2

Да, я знаю, что если мы не называем «абстрактный» метод мы не будем знать, что он не объявлен. Это «очарование» интерпретируемых языков :) Мы не знаем, есть ли какая-либо ошибка, пока код не будет запущен. Хотя, было бы здорово, если бы мы знали об этом как можно раньше. Например, как только экземпляр класса FantasticBehavior привязан к модели, мы могли бы перебросить некоторый дочерний элемент CException, чтобы показать, какие требуемые методы должны быть объявлены в модели. Для того чтобы достигнуть этого можно использовать что-то вроде перечисленных ниже:

class FantasticBehavior extends CActiveRecordBehavior 
{ 

    public function attach($owner) 
    { 

     if(!/*$owner has declared methods list this->abstractMethods*/) 
     { 
      throw new CAbstractMethodNotDecalared('....'); 
     } 

     parent::attach($owner);  
    } 

    public function abstractMethods() 
    { 
     return array('prepareForFantastic'); 
    } 

} 

Нам необходимо переопределить метод attach из класса CBehavior и проверить, если объявлена ​​«абстрактная» метода. Метод abstractMethods используется для получения списка «абстрактного» метода.

Не знаю, существует ли attachBehavior событие существует. Если это так, мы можем использовать его вместо переопределения метода attach.

Использование этой идеи Базовый класс для поведения с «абстрактными» методами.

Что вы думаете об этом?

Возможно, в будущем я сделаю расширение для Yii и стану знаменитым и богатым? :))

ответ

2

Это может быть немного запутанным, чтобы объяснить ...

Нет, вы не можете «прикрепить» абстрактные методы для вашей модели CActiveRecord с помощью Yii's Behaviors. Все действия Behavior - это некоторые умные переопределения __call(), __get() и __set(), которые дают иллюзию множественного наследования. (This is a good article about it). Поведения не обеспечивают true Поддержка «множественного наследования» для функций основного языка, таких как абстрактные классы и интерфейсы. Поэтому, если вы присоедините это поведение и добавьте doSomethingFantastic() в ваш класс CActiveRecord, вы все равно получите сообщение об ошибке.

Вы можете, конечно, объявить абстрактное поведение, которое отличается от других Поведение. Так что если вы создали другое SuperFantasticBehavior Поведение, которое расширило FantasticBehavior и внедрило doSomethingFantastic() в его, со мной все будет в порядке. Но это не заставит вас объявить метод doSomethingFantastic() в самом CActiveRecord.

Для немного более глубокого понимания: Путь CComponent::_call() переопределение Yii структурирована, при вызове метода он будет первым увидеть, если какой-либо из поведения у этого метода, и вызовите метод самого класса.

Поведение кажется классным сначала (mixins!), Но иногда лучше помнить, что PHP - это single class inheritance language, и сохранить это просто. ;)

UPDATE:

Разница заключается в том, что, если вы могли бы использовать абстрактные методы в этом случае вы увидите «Класс должен реализовывать метод» сообщение об ошибке при попытке запустить свой код (любого кода) , и ваша IDE выделит ошибку. Это скорее «ошибка компиляции» (не то, что она действительно существует в интерпретируемом языке, таком как PHP).

Вместо этого вы увидите ошибку «не объявленного метода» (как вы упоминаете) во время выполнения. Но вы не увидите этого до тех пор, пока этот метод не будет называться, что означает, что вы не получите такого хорошего раннего предупреждения, как абстрактное определение. И если этот метод никогда не вызывал, вы не получите ошибку, что означает, что она не «обязывает» декларацию так же, как абстрактный def.

Извините, если мой первоначальный ответ начинался с слишком низкого уровня, я просто хотел убедиться, что не было никакого недоразумения. Это интересная дискуссия, и я задумался над тем, что действительно делает абстрактная декларация. Спасибо, и счастливое кодирование! :)

Cheers

+0

Hi. Спасибо за ваш ответ. См. Обновленное сообщение. –

+0

Привет снова :) См. Обновленное сообщение :) И счастливое кодирование для вас тоже. –