PPP PHP question v2 – the humbler post

Obviously I rubbed some people the wrong way, and didn’t explain my question(s) clearly enough from the outset, then got wrapped up in taking some offense from some of the responses.  Reviewing everything today I can see where I could have responded differently, and more clearly, earlier on.  Apologies to anyone who was offended (if anyone was).

I do think the original point(s) were somewhat lost.  To the original poster who offered the banking analogy – thank you.  However, I don’t think it’s enough, and is clearly at odds with some of my other experiences with Java/Groovy.  Let me show two code samples here (assuming WP doesn’t mangle the code too much – I need to get one of those code display plugins in here!)

In Groovy (Java), if I run this:

===========================
class person {
private email = “person email”
protected phone = “person phone”
public name = “person name”
def showInfo() {
println this.email + ” ” + this.name + ” ” + this.phone
this.onlyInUser()
}
}
class user extends person {
private email = “user email”
protected phone = “user phone”
public name = “user name”
def onlyInUser() {
println “I’m in the user class definition”
}
def showInfo() {
super.showInfo()
println this.email + ” ” + this.name + ” ” + this.phone
}
}
def u = new user()
u.showInfo()
===========================
I get this output:

===========================
person email person name person phone
I’m in the user class definition
user email user name user phone
===========================

*All* the *this* property accesses are class-bound, it seems, but the this.onlyInUser() call still calls the method in the child class.

In C# (my C# isn’t hot, but this *seems* to be a correct re-implementation of the same logic) if I run :

===========================

using System;
class person  {
public string name = “person name”;
protected string email= “person email”;
private string phone = “person phone”;

public virtual void showInfo() {
Console.WriteLine(“In the person showInfo method”);
Console.WriteLine( this.name + ” ” + this.phone + ” ” + this.email);
}
}

class User : person {
public new string name = “user name”;
protected new string email= “user email”;
private new string phone = “user phone”;

public override void showInfo() {
base.showInfo();
Console.WriteLine(“In the user showInfo method”);
Console.WriteLine( this.name + ” ” + this.phone + ” ” + this.email);
}

// Main begins program execution.
public static void Main()
{
User u = new User();
u.showInfo();
}
}

===========================

I get

===========================

In the person showInfo method
person name person phone person email
In the user showInfo method
user name user phone user email

===========================

Running seemingly equivalent code in PHP (5.2.5)
===========================
<?php
error_reporting(E_ALL);
class person {
private $email = “private person email”;
protected $phone = “protected person phone”;
public $name = “public person name”;
public function showInfo() {
echo $this->email.” – “.$this->phone.” – “.$this->name.”\n”;
$this->onlyInUser();
}
}
class user extends person {
private $email = “private user email”;
protected $phone = “protected user phone”;
public $name = “public user name”;
public function onlyInUser() {
echo “I’m in the user class definition\n”;
}
public function showInfo() {
parent::showInfo();
echo $this->email.” – “.$this->phone.” – “.$this->name.”\n”;
}
}
$u = new user();
$u->showInfo();
===========================
I get the following output:

===========================
private person email – protected user phone – public user name
I’m in the user class definition
private user email – protected user phone – public user name
===========================

There’s clearly a difference here, and it’s likely related to an logical difference between super and parent.  My limited Java-fu and C#-fu being what they are, I’m not able to quite grok why there’s a difference in behaviour between the examples ago.

Hopefully this is humble enough to garner some collective wisdom.  I’m not bashing PHP here, nor anyone’s contributions or anything of the sort.  Simply asking – why are these behaving differently?


I'm currently working on a book for web freelancers, covering everything you need to know to get started or just get better. Want to stay updated? Sign up for my mailing list to get updates when the book is ready to be released!

Web Developer Freelancing Handbook

Be Sociable, Share!

{ 12 comments to read ... please submit one more! }

  1. What you are running into here is a separate issue altogether from access modifiers. The reason that Java (and evidently c#) is behaving this way is due to Field Hiding. In Java, if you redeclare a member variable in a subclass that was already defined in your parent class you are actually creating a completely separate space in the instance’s symbol table for that variable meanwhile, the original variable from the super class is still alive and well. The downside is that you cannot actually access that variable from your child class using ‘this’. This can sort of be demonstrated if you used super.phone or super.name (super.email will not work due to private access modifier).

    PHP does not operate in this way at all. The quick and dirty explanation is that when you redeclare protected and public variables in PHP new spaces in memory are not created, it essentially uses the same space previously occupied by your parent class’ variables. This is not true however for private variables. They will get their own distinct spaces. This can be shown somewhat if you were to run the following code:

     

    You will see that output:

    object(B)#1 (4) {
      ["var1:private"]=>
      string(9) "B private"
      ["var2:protected"]=>
      string(11) "B protected"
      ["var3"]=>
      string(8) "B public"
      ["var1:private"]=>
      string(9) "A private"
    }
    array(4) {
      ["Bvar1"]=>
      string(9) "B private"
      ["*var2"]=>
      string(11) "B protected"
      ["var3"]=>
      string(8) "B public"
      ["Avar1"]=>
      string(9) "A private"
    }
    

    So, php is indeed slightly different in that it does not allow ‘Hiding Fields’ (http://java.sun.com/docs/books/tutorial/java/IandI/hidevariables.html) I will not say which way I think is correct as that is very subjective and could be argued both ways. There are valid reasons for both. But you can definitely say that it is different!

  2. I apologize, the php code was evidently eaten…

    class A
    {
            private $var1 = 'A private';
            protected $var2 = 'A protected';
            public $var3 = 'A public';
    }
    
    class B extends A
    {
            private $var1 = 'B private';
            protected $var2 = 'B protected';
            public $var3 = 'B public';
    }
    
    var_dump(new B());
    var_dump((array)new B());
    
  3. Thank you for that. The C# requires the ‘new’ keyword in the subclass, which was a big hint that something different is going on.

    I’ve fielded multiple questions from Java people in the past several months that touched on this subject, and when I showed the above PHP code to some Java-ish friends, they did not expect the PHP behaviour. It’s not as if it can not be understood, eventually, but it’s not what some people expect right off the bat.

  4. Being a PHPite, I’m biased. Ok, now that that is out of the way…
    I find the Java implementation really strange. Part of the reason for extending classes is to override properties and methods, so the PHP implementation makes a lot of sense to me. Does this mean that if I did the following in Java:

    class user extends person{
    protected email = 'me@example.com';
    }
    
    def u = new user()
    u.showInfo()
    

    it would actually output:

    In the person showInfo method
    person name person phone person email
    

    ?

    Or is this case different since the method was never overridden in the child class?
    Do you have to override the method to make use of the property?

  5. It is the same as Michael’s example. It isn’t because you aren’t redeclaring the method that it behaves this way, it is because you are redeclaring the property. Part of the difference is that PHP allows a developer to be lazy and makes it very convenient to set initial values for properties outside of the constructor.

    Traditionally you would only ever assign values to these properties in the constructor and do little more then declare them inside of your class definition.

  6. Michael, thank you for taking the time to make this post. I had not realized this behavior existed in php. I made it a point to sit down with my co-workers and compare the differences between php, C++ and Java.

  7. @herman – Glad it helped.

  8. When you first think about it you say, “huh, that’s weird.” But then you think about it more and you think, “No, that’s they only way it makes sense, private access *has* to work that way.” And that’s where most people stop thinking. But if you think about it a little bit more you realize that it can be pretty confusing.

    Because, private affects visibility && inheritability, whereas protected only affects visibility and public affects neither.

    Btw, in Java, if you subclass and override a protected attribute, you get a new copy just like PHP’s private accessor (but not its private).

    The troubling part of all of this is that the simple explanation of OOP classes is that they ‘define objects’ is partially untrue, or at least over simplified to the point of being confusing.

    From Wikipedia:
    “Class: Defines the abstract characteristics of a thing (object), including the thing’s characteristics (its attributes, fields or properties) and the thing’s behaviors (the things it can do, or methods, operations or features). One might say that a class is a blueprint or factory that describes the nature of something.”

    So, when people read that, then see something like

    class foo {
    private $b
    }

    they want to think that the data in $b is privately held against instances of class ‘foo’. But really, the access to data in $b is held against the calling context of class foo. Which, although valid (and probably more sane than an alternative), does not define characteristics of the *object*, but the context in which it is used/invoked/called.

  9. Syntax error:

    Btw, in Java, if you subclass and override a protected attribute, you get a new copy just like PHP’s private accessor (but not its private).

    … (but not its PROTECTED)

  10. Wow Mark, you were far more eloquent in that than I was. Understanding when developing and understanding to the point where you can explain it to multiple other people is what’s been my biggest issue so far with all of this. Then on top of that, trying to make sense of the different approaches different languages take added even more confusion. Mike’s reply above helped – “field hiding” vs “access modifiers” terminology helps, but PHP’s own manual uses the term “visibility”, which fall more in line with the concept of ‘hiding.

  11. This is a test response.

  12. Michael, thank you for taking the time to make this post. I had not realized this behavior existed in php. I made it a point to sit down with my co-workers and compare the differences between php, C++ and Java.

{ 0 Pingbacks/Trackbacks }

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>