I originally wrote a long af reply ... but now I agree that this is a bug as 
well after writing it out ...

I’ll be referring to the following code:

class A {
  protected int $v = 1;
}

class B extends A {}

class C extends A {
  protected int $v = 2;
}

class D extends A {
  protected int $v = 3 { get => $this->v * 2 }
}

---

Reason 1:
Changing the value changes the contract of it's parent.

This is also possible indirectly without changing the contract in C:

class C extends A {
  public function __construct() {
    $this->v = 2;
  }
}

This is effectively the same thing as redeclaring it and setting a different 
value for $v.

---

Reason 2:
Changing the behaviour changes the contract of it's parent.

This is also possible indirectly without changing the contract in D:

class D extends A {
  private int $_v;
  public function __construct() {
    $this->_v = $this->v;
    unset($this->v);
  }
  public function __set($name, $value) {
    $name = "_{$name}";
    $this->{$name} = $value;
  }
  public function __get($name) {
    $name = "_{$name}";
    return $this->{$name};
  }
}

Thus I think since this is already possible, making it more explicit vs. this 
wordy and round-about way of doing the same thing shouldn’t be necessary.

---

In both the examples above, a sibling class would still be able to access $v, 
even though the default value and/or behaviour change completely. However, if 
you make it more obvious that this is the case (by using hooks and/or changing 
the default value), you can’t access it from a sibling.

Reply via email to