0

Could someone explain me, why is it possible to do the following in PHP, but, for example, not in C# or Java:

Class A {
    protected $a = 'Howdy!';
}

Class B extends A {
    public function howdy() {
        $created = new A();
        echo $created->a; <----- This is legal due to per-class visibility
    }
}

$b = new B();
echo $b->howdy();  <----- Hence, no fatal error here

This behavior seems to be specified here, but I can't understand the fundamental reason behind this (to my mind, one can't simply implement the per-class visibility instead of the per-instance one without having a strong reason for that).

Yippie-Ki-Yay
  • 22,026
  • 26
  • 90
  • 148
  • 3
    I might be missing something, but why shouldn't this be possible? You're calling a public function from an object. That functions creates an object (internally) which echoes a variable from an object that it has access to. What is the issue? – Nanne May 18 '12 at 13:58
  • 3
    Why are you expecting a fatal error? There are no member visibility errors. `B` can see all of `A` that is `public` or `protected`. – Dan Lugg May 18 '12 at 14:01
  • 2
    Asking why something does or doesnt work in Lang X but not in Lang Y is usually pointless. They are different languages, so they may differ. And in this particular case your assumption is wrong. So no question here. – Gordon May 18 '12 at 14:02
  • @Nanne This **might be possible,** but several other languages forbid it and that caused my confusion (e.g http://stackoverflow.com/questions/10657545/c-sharp-accessing-protected-member-in-derived-class) Anyway, I was interested in fundamental reasons behind this decision *(this is not the kind of thing you'd invent while having your morning cup of coffee).* – Yippie-Ki-Yay May 18 '12 at 18:17
  • @Gordon I agree with your first statement, but exactly which of my assumptions is wrong? – Yippie-Ki-Yay May 18 '12 at 18:19
  • @Yippie-Kai-Yay your implicit assumption that they should work alike in this case. – Gordon May 18 '12 at 19:19

5 Answers5

2

That is also possible in C# (and Java for that matter).

class A                               // declare new class type B
{
   protected string a = "Howdy!";     // that has a protected member called `a`
}

class B : A                           // declare new type B which extends type A
{
   public void howdy()
   {
       A created = new A();
       Console.WriteLine(created.a);  // no problem accessing a b/c B extends A
   }
}


B bInst = new B();                    // create a new instance of type B
bInst.howdy();                        // invoke it's public method howdy()

Basically what is going on is this:

  • class A contains a protected member called a which means it is visible in the scope of classes which extend A (in our case class B)
  • class B extend a so it has access to it's protected members (in our case to a)
Mike Dinescu
  • 54,171
  • 16
  • 118
  • 151
  • I guess this is incorrect, see http://stackoverflow.com/questions/10657545/c-sharp-accessing-protected-member-in-derived-class – Yippie-Ki-Yay May 18 '12 at 18:13
  • 1
    This is incorrect. PHP implements security on the class level, not on the instance level. Other languages implement it on the instance level. Both have pros and cons... – ircmaxell May 18 '12 at 19:15
2

It is possible to do in both C# and Java as well. protected means the variable is accessible from any subclass of A. B is a subclass of A, hence it can access the variable. There's no magic here.

Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308
2

The page you linked to has a section titled "Visibility from other objects" which states that:

Objects of the same type will have access to each others private and protected members even though they are not the same instances. This is because the implementation specific details are already known when inside those objects.

rid
  • 61,078
  • 31
  • 152
  • 193
  • Yes, but what's behind this decision? Why would anyone invent this kind of rule and add it to the language specification? I certainly understand that `PHP` designers have a right to do what they want to do, but this behavior differs from the similiar behavior in other languages and that should probably have some strong reason behind it. – Yippie-Ki-Yay May 18 '12 at 18:24
2

The reason it doesn't work is, as you specified, PHP implements access control on a class level, where other languages use an instance level approach.

Why is it useful? It allows your classes to operate on other instances of itself without exposing its private data. Let's take a simple value-object example:

class Int {
    protected $value = 0;
    public function __construct($value) {
        $this->value = (int) $value;
    }
    public function add(Int $new) {
        return new Int($new->value + $this->value);
    }
}

$a = new Int(1);
$b = new Int(2);
$c = $a->add($b);

This lets you keep protected info encapsulated, yet still work with it across instances...

There are pros and cons to both approaches...

ircmaxell
  • 163,128
  • 34
  • 264
  • 314
0

It wouldn't work if you'd done this:

$b = new B();
echo $b->a;

In your example, you're not accessing the $a member direct from B(). You're accessing it from an A() object that happens to have been instantiated from inside B().

Marc B
  • 356,200
  • 43
  • 426
  • 500