0

I was reading through some PHP code, and I noticed a class calling a protected method on its sibling (inherited from a common parent). This strikes me as counter-intuitive.

Does in the same inheritance tree in PHP mean something like Java's part of the same package ?

I'm more used to the C# meaning of protected.

Because I am more used to C#'s meaning of protected, I was not expecting to be able to call the protected method on a sibling class. In Java, the distinction is clear from the package. Is there anything, other than inheritance, that defines accessibility in this instance in PHP?

<?

class C1
{
    protected function f()
    {
        echo "c1\n";
    }
}

class C2 extends C1
{
    protected function f()
    {
        echo "c2\n";
    }
}

class C3 extends C1
{
    public function f()
    {
        // Calling protected method on parent.
        $c1 = new C1();
        $c1 -> f();

        // Calling protected method on sibling??!?
        $c2 = new C2();
        $c2 -> f();

        echo "c3\n";
    }
}

$c3 = new C3();
$c3 -> f();

// OUTPUT:
// c1
// c2
// c3

Here's me trying to the same thing in C# (and failing).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class c1
    {
        protected void f()
        {
            Console.WriteLine("c1");
        }
    }
    class c2: c1
    {
        protected void f()
        {
            Console.WriteLine("c2");
        }
        public void g()
        {
            Console.WriteLine("g!");
        }
    }

    class c3 : c1
    {
        protected void f()
        {
            // Error    1   Cannot access protected member 'ConsoleApplication2.c1.f()' 
            //  via a qualifier of type 'ConsoleApplication2.c1'; the qualifier must be 
            // of type 'ConsoleApplication2.c3' (or derived from it)    
            //c1 cone = new c1();
            //cone.f();

            base.f();

            c2 ctwo = new c2();
            //Error 1   'ConsoleApplication2.c2.f()' is inaccessible due to its protection level
            ctwo.f();
            ctwo.g();


            Console.WriteLine("c3");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            c3 cthree = new c3();
            // Error    2   'ConsoleApplication2.c3.f()' is inaccessible due to its protection level
            cthree.f();
        }
    }
}

It looks like the behaviour expected was the case prior to PHP 5.2. This RFC explains the issue a little more, and points to why the change happened in this bug.

I'm not sure it quite answers my question, but I thought I'd update the question, in case it helps anyone.

Thanks to Robin F., for pointing me to this discussion of the RFC, for some background.

Community
  • 1
  • 1
Peter K.
  • 8,028
  • 4
  • 48
  • 73
  • 1
    Try to search before asking > http://php.net/manual/en/language.oop5.visibility.php – Svetoslav Oct 21 '13 at 13:56
  • @Svetlio: None of that answers my question, which is why I asked it here. Except this addition: http://www.php.net/manual/en/language.oop5.visibility.php#93743 Please read the question before posting. – Peter K. Oct 21 '13 at 14:00
  • Sorry but I don't understand why this sound weird to you... Could you explain it better? To me is all fine (and not counter intuitive) – DonCallisto Oct 21 '13 at 14:07
  • @DonCallisto: See edit. Basically, because I am more used to C#'s version, and because PHP does not appear to use namespace / package definitions to restrict access as Java does. – Peter K. Oct 21 '13 at 14:11
  • 1
    C3 is not calling the protected method on sibling but the protected method on parent overrided by C2. If you try to call a protected method on C2 wich doesn't exist on C1, you've got a fatal error. – scraaappy Oct 21 '13 at 14:27
  • @PeterK. as I told you there is documentation. In C3 you have access to C1 methods and if you call it even from C2 you can access it. Try dumping get_class_methods('C2') and you will find that there aren't C2 methods at $c2 "Members declared protected can be accessed only within the class itself and by inherited and parent classes" – Svetoslav Oct 21 '13 at 14:34
  • @Svetlio But my example code contradicts "Members declared protected can be accessed only within the class itself and by inherited and parent classes". `C3` is not a parent of `C2` nor does it inherit from `C2`, and yet it is allowed to call a protected method. – Peter K. Oct 21 '13 at 14:58
  • see comment above ;) C3 is not allowed to call a protected method from C2 – scraaappy Oct 21 '13 at 15:16
  • @scraaappy: OK... but why is it in my example code? – Peter K. Oct 21 '13 at 15:18
  • Hi! see my edit with an example from Java world. – FazoM Apr 30 '14 at 15:46

3 Answers3

2

To me there isn't nothing out-of-order. protected means visible to this class and all his subclasses.

Let's analyze this snippet

class C3 extends C1
{
  public function f()
  {
    // Calling protected method on parent.
    $c1 = new C1();
    $c1 -> f();

    // Calling protected method on sibling??!?
    $c2 = new C2();
    $c2 -> f();

    echo "c3\n";
  }
}

You're overwriting C1->f() [and this is fine] but first time you're recalling $c1->f() (as $c1 is an instance of C1 class) and so output is perfectly ok.
Second time you're calling $c2->f() so no sibling function but C2 class function and this is perfectly legal as you're overwriting this too.

Maybe I don't understand properly your question, but this is the explaination of the above snippet of code

DonCallisto
  • 29,419
  • 9
  • 72
  • 100
  • Thanks for the explanation! I'm still not getting it, though. The call in `$c2 -> f()` is coming from class `C3`, which (to my way of C# thinking) should not be possible for protected methods. – Peter K. Oct 21 '13 at 14:20
  • @PeterK. : are you sure that this example, writte in c# language, provide a different result? (I'm asking because I don't remember well C# underlying mechanisms; and I'm not sure about what you're saying here) – DonCallisto Oct 21 '13 at 14:24
  • Done! As you can see, the IDE keeps saying `'f()' is inaccessible due to its protection level` – Peter K. Oct 21 '13 at 15:00
  • @PeterK.: ok now I can see it... Yes it seems different from c# world – DonCallisto Oct 21 '13 at 15:32
0

It looks like the behaviour expected was the case prior to PHP 5.2. This RFC explains the issue a little more, and points to why the change happened in this bug.

I'm not sure it quite answers my question, but I thought I'd update the question, in case it helps anyone.

Thanks to Robin F., for pointing me to this discussion of the RFC, for some background.

Peter K.
  • 8,028
  • 4
  • 48
  • 73
-1

According to Wikipedia (http://en.wikipedia.org/wiki/Php):

Objects of the same type have access to each other's private and protected members even though they are not the same instance.

EDIT:

See code snippet (in Java):

public class SimpleApp {

    public static void main(String[] args) {
        SimpleApp s = new SimpleApp();
        s.method(); // interesting?!
    }

    private void method() {
        System.out.println("This is private method!");
    }
}

When run, in the console there will be message displayed.
I guess this is because of how compilator (or for PHP interpreter) is implemented.

In this case you are inside SimpleApp class, so you can call its private method (even on different object - from outside). It might be different for C#.

FazoM
  • 4,777
  • 6
  • 43
  • 61