Trait: не переопределить свойство

vasa_c

Новичок
Подскажите, пожалуйста, это пыхобаг или я невдупляю во что-то фундаментальное.
Есть два кода:

PHP:
abstract class ParentClass
{
    public $flag = true;
}

class ChildClass extends ParentClass
{
    public $flag = false;
}

var_dump((new ChildClass())->flag); // false
PHP:
abstract class ParentClass
{
    public $flag = true;
}

trait TFlag
{
    public $flag = false;
}

class ChildClass extends ParentClass
{
    use TFlag;
}
Первый работает, как и предполагается, второй валится с "PHP Fatal error: ParentClass and TFlag define the same property ($flag) in the composition of ChildClass. However, the definition differs and is considered incompatible."

С методами же всё работает нормально:

PHP:
abstract class ParentClass
{
    public function flag(): bool
    {
        return true;
    }
}

trait TFlag
{
    public function flag(): bool
    {
        return false;
    }
}

class ChildClass extends ParentClass
{
    use TFlag;
}

var_dump((new ChildClass())->flag()); // false
 

vasa_c

Новичок
Может быть действительно не вдупляю, но момент всё равно запутанный. Кто подразумевается под "a class"? В документации все примеры с одним классом и трейтом. Я же его вставляю в ChildClass, где свойство не переопределяется.

Если смотреть с точки зрения, что трейты это копи-паста, то написанное в доке логично. Получается два определения одного свойства в рамках описания одного класса. В семёрке же сжалились и разрешают делать два идентичных.
Но здесь же свойство из ParentClass наследуется.
 

MiksIr

miksir@home:~$
> Но здесь же свойство из ParentClass наследуется.
И что, оно от этого перестает быть переопределяемым?
 

vasa_c

Новичок
MiksIr, что вы вкладываете в понятие "переопределяемое" в данном случае?
 

vasa_c

Новичок
@grigori я воспользовался этим базовым термином в первом куске кода. Переопределил инициализирующее значение для свойства. И пых это прекрасно съел, для него это не было incompatible signature. Вот если бы поменял public на protected, тогда да. То есть с "переопределением" в этом смысле этого слова всё впорядке.

Потом я просто вынес кусок кода из одного класса в трейт и тут пошли проблемы. В доке приведённой fixxxer'ом я не вижу ни одного слова, которое можно перевести, как "переопределяемое".
 

WMix

герр M:)ller
Партнер клуба
Свойство класса уже определено, переписать его значение можно всегда в конструкторе, то что ты пытаешься сделать заранее описано как конфликт. Вся остальная болтовня ни к чему не ведет.
Код:
class ChildClass extends ParentClass
{
    public function __construct(){
      $this->flag=false;
    }
}
 

vasa_c

Новичок
@WMix если болтовня моя не нравится, я без вопросов вас от неё избавляю. Случай попался совершенно единичный, переживу без трейта.

Но где заранее описан именно этот вариант, я не увидел.

И трейт нужен, чтобы его можно было просто вставлять в классы со всем его содержимым, если я должен каждый раз ещё и конструктор переопределять, то зачем он нужен? Я и без всякого конструктора просто свойство переопределю.
 

WMix

герр M:)ller
Партнер клуба
Ссылка ведет прямо на описание этого случая.
Если трейт определяет свойство, то класс не может определить свойство с таким же именем, кроме случаев полного совпадения (те же начальное значение и модификатор видимости), иначе будет сгенерирована фатальная ошибка.
даже простое предопределение свойства уже попахивает не говоря о трейте и так между нами конструктор как раз для этого изначально и задумывался как установщик значений свойств.
Я и без всякого конструктора просто свойство переопределю.
Ктож сомневается что люди говнять могут, что разницу между классом и обьектом не понимают
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
Каким образом свойство оказалось определено в классе, явным, или через наследование, или через другой trait - не имеет значения.

Если эта формулировка кажется недостаточно понятной, можете завести documentation issue на bugs.php.net и предложить формулировку лучше.
 

Adelf

Administrator
Команда форума
Я бы посоветовал просто не юзать трейты. Они - зло.
 
Сверху