Я задал себе тот же вопрос сегодня, и я хотел бы добавить свои два цента.
Причина, по которой мы хотели бы иметь свойства abstract
, заключается в том, чтобы убедиться, что подклассы определяют их и генерируют исключения, когда они этого не делают. В моем конкретном случае мне нужно было что-то, что могло бы работать с static
союзником.
В идеале я хотел бы что-то вроде этого:
abstract class A {
abstract protected static $prop;
}
class B extends A {
protected static $prop = 'B prop'; // $prop defined, B loads successfully
}
class C extends A {
// throws an exception when loading C for the first time because $prop
// is not defined.
}
Я закончил с этой реализацией
abstract class A
{
// no $prop definition in A!
public static final function getProp()
{
return static::$prop;
}
}
class B extends A
{
protected static $prop = 'B prop';
}
class C extends A
{
}
Как вы можете видеть, в A
я не определяю $prop
, но я использую его в static
геттере. Поэтому следующий код работает
B::getProp();
// => 'B prop'
$b = new B();
$b->getProp();
// => 'B prop'
В C
, с другой стороны, я не определяю $prop
, поэтому я получаю исключения:
C::getProp();
// => Exception!
$c = new C();
$c->getProp();
// => Exception!
Я должен вызовите метод getProp()
, чтобы получить исключение, и я не могу получить его при загрузке класса, но это довольно близко к желаемому поведению, по крайней мере, в моем случае.
Я определяю getProp()
как final
, чтобы избежать того, что какой-то умный парень (он же через 6 месяцев) испытывает искушение сделать
class D extends A {
public static function getProp() {
// really smart
}
}
D::getProp();
// => no exception...
Вы можете просто запустить генератор и игнорировать модели / миграции / фикстуры.
ruby script/generate rspec_model User --skip-migration --skip-fixture --skip
Я собирался написать что-нибудь для этого, но никто не заинтересовался этим.