«Абстрактные» методы в поведении Yii - PullRequest
2 голосов
/ 29 февраля 2012

Я занимаюсь разработкой приложения 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 и стану известным и богатым?:))

1 Ответ

2 голосов
/ 02 марта 2012

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

Нет, вы не можете "прикрепить" абстрактные методы к вашей модели CActiveRecord, используя Поведение Yii . Все, что делает Поведение, - это некоторые умные переопределения __call(), __get() и __set(), которые дают иллюзию множественного наследования. ( Это хорошая статья об этом ). Поведения не обеспечивают true поддержку «множественного наследования» для основных функций языка, таких как абстрактные классы и интерфейсы. Поэтому, если вы присоедините это поведение и добавите doSomethingFantastic() к своему CActiveRecord классу, вы все равно получите ошибку.

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

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

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

ОБНОВЛЕНИЕ:

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

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

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

Приветствия * * тысяча пятьдесят-один

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