On 25/05/2018 19:48, Pedro Magalhães wrote:
On Fri, May 25, 2018 at 6:47 PM, Rowan Collins
<rowan.coll...@gmail.com <mailto:rowan.coll...@gmail.com>> wrote:
I'm not sure what exactly is "ambiguous" or "might change" here. The
current text accurately describes what "protected" means in PHP,
and in
many other languages: a property which may be accessed only within the
current class, classes inheriting from it, and classes from which it
inherits.
I think that what the note may be referring to is the fact that
currently, a child class can access the protected members of another
child class if this member was declared on the parent class.
However, this is a bug as described on
https://bugs.php.net/bug.php?id=50892 which hasn't been fixed yet as
the potential BC break makes it more suitable for a major version.
Again, this is perfectly reasonable if you consider polymorphism:
- Access is class-based, not instance-based: you can call private
members of a different instance of the same class.
- For the same reason, you can access protected members on an instance
of a parent class.
- If you ask for an instance of class A, you may at run-time actually
receive an instance of some sub-class of A.
- So, if classes B1 and B2 both inherit from A, a method on class B1
might ask for an instance of A, and be given an instance of B2; when it
calls a method on that instance, it's the definition in B2 which will be
accessed.
Here's a concrete example (copied below): https://3v4l.org/LeClo
Note that this example also works in Java:
https://tio.run/##vZMxb9swEIVn61fcKKctbWctMhUIuhgomqIdigwn8mIxpUiDPNkpDP92hxJlW4rsIUBRQhP5@O670@MzbvDTs/pzOGAR2KNkkAZDgG9eS4JdBnGtvWOSTAqUqwtDsEFT0@f2LAnirpbpTt7XTDuHZnGpg2h34a7vsD/7nBhGFVfE33H7s7mVT8eVz6p75yvkeLPT9gBmM/iCxgTAnn9FXDoF7gm2pZYlbciDLLVR3Rx0aMFPJp649haWyKXwrrYqb/sa8E1HjXWYG6cVoFJ5mq7jkvy/IGyNLg36w106Exfmt8/2WZYsfuDLvSdKVPTCZNWbBCT@ge7qjw71mnyeto@lLudoQNVz6IZ8bmRE3CL80lxGpCHxbpTIo@x/AsMNLMRtDzvriBL@ErWN1yfdZmDkYzyqeJQ/sNd29fsR0K9CU2gySUPH@HYsbQd/Il/MxTyCHzVFp@k3f9Y8/A1MlXA1i3UswsbmKC48nGvi4qo4fjHAX8nTR0AL2sa2bBPzp2FwttoYQCkpvA16VcRsR3mfPLqiaN5M8W78ZvCHwys
abstract class Price {
protected $value;
public function __construct($value) {
$this->value = $value;
}
// Duck typing means this declaration is actually optional
abstract protected function getRawValue();
public function getFormattedValue() {
// Calls a protected method of whichever child class is $this
return number_format($this->getRawValue(), 2);
}
public function add(Price $other) {
// Calls a protected method of whichever child class is $other
$this->value += $other->getRawValue();
}
}
class TaxFreePrice extends Price {
protected function getRawValue() {
return $this->value;
}
}
class PriceWithTax extends Price{
const TAX_RATE=1.2;
protected function getRawValue() {
return $this->value * self::TAX_RATE;
}
}
$a = new TaxFreePrice(10);
$b = new PriceWithTax(10);
echo $a->getFormattedValue(), PHP_EOL;
echo $b->getFormattedValue(), PHP_EOL;
// Here, an instance of TaxFreePrice will access a protected member of
PriceWithTax
$a->add($b);
echo $a->getFormattedValue(), PHP_EOL;
Regards,
--
Rowan Collins
[IMSoP]