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]

Reply via email to