Page 2 of 3
Posted: Sat Jan 14, 2006 9:17 pm
by Jenk
but as my example shows.. what happens if you extend the class and overload the getBalance() method? You won't get the balance.. infact, do anything in the child class and it won't affect the balance.
Here is a slight modification to show the exact problem with using private:
Code: Select all
<?php
class A
{
private $var = 1;
function setVar ($val)
{
$this->var = $val;
}
function getVar ()
{
return $this->var;
}
}
class B extends A
{
function setVar ($val)
{
$this->var = $val;
echo "var set!\n";
}
}
$a = new A;
$b = new B;
$a->setVar('a');
print $a->getVar()."\n";
$b->setVar('b');
print $b->getVar()."\n";
?>
Outputs:
and yet overloading the getVar() method
as well as the setVar method works as the above should work.. even if it is overloaded with the exact same:
Code: Select all
<?php
class A
{
private $var = 1;
function setVar ($val)
{
$this->var = $val;
}
function getVar ()
{
return $this->var;
}
}
class B extends A
{
function setVar ($val)
{
$this->var = $val;
echo "var set!\n";
}
function getVar ()
{
return $this->var;
}
}
$a = new A;
$b = new B;
$a->setVar('a');
print $a->getVar()."\n";
$b->setVar('b');
print $b->getVar()."\n";
?>
Outputs:
Posted: Sun Jan 15, 2006 12:39 am
by Christopher
Jenk wrote:and yet overloading the getVar() method as well as the setVar method works as the above should work.. even if it is overloaded with the exact same:
Actually I don't think this is quite right. I believe that $var in A would not be visible to B, so $var in B would be a separate variable. Try this
Code: Select all
<?php
class A
{
private $var = 1;
function setVar ($val)
{
$this->var = $val;
}
function getVar ()
{
return $this->var;
}
function setVar2 ($val)
{
$this->var = $val;
}
function getVar2 ()
{
return $this->var;
}
}
class B extends A
{
function setVar ($val)
{
$this->var = $val;
echo "var set!\n";
}
function getVar ()
{
return $this->var;
}
}
$a = new A;
$b = new B;
$a->setVar('a');
print $a->getVar()."\n";
$b->setVar('b');
print $b->getVar()."\n";
print $b->getVar2()."\n";
$b->setVar2(2);
print $b->getVar2()."\n";
?>
Posted: Sun Jan 15, 2006 12:57 am
by feyd
small issue for both of you: you're trying to access a private variable in an extended class, which is going to net you a nice fat error.
Code: Select all
[feyd@home]>php -r "class a { private $a = 1; function getVar() { return $this->a; } } class b extends a { function getVar() { return $this->a; } } $t1 = new a(); $t2 = new b(); var_dump($t1->getVar(),$t2->getVar());"
PHP Notice: Undefined property: b::$a in Command line code on line 1
Notice: Undefined property: b::$a in Command line code on line 1
int(1)
NULL
[feyd@home]>php -r "class a { protected $a = 1; function getVar() { return $this->a; } } class b extends a { function getVar() { return $this->a; } } $t1 = new a(); $t2 = new b(); var_dump($t1->getVar(),$t2->getVar());"
int(1)
int(1)
granted, calling setVar() in b will make a separate variable come into existance..
Posted: Sun Jan 15, 2006 1:51 am
by Christopher
feyd wrote:small issue for both of you: you're trying to access a private variable in an extended class, which is going to net you a nice fat error.
granted, calling setVar() in b will make a separate variable come into existance..
Correct. Both of those things were what I was trying to demonstrate. Which means Private works as documented.
Posted: Sun Jan 15, 2006 10:51 am
by Jenk
and raises problems which I was trying to show..
Posted: Sun Jan 15, 2006 11:20 am
by Christopher
Jenk wrote:and raises problems which I was trying to show..
What are the problems?
Posted: Mon Jan 16, 2006 10:34 am
by Maugrim_The_Reaper
Jenk wrote:
but as my example shows.. what happens if you extend the class and overload the getBalance() method? You won't get the balance.. infact, do anything in the child class and it won't affect the balance.
Which is why the parent - due to overloading - just might be an abstract. Even if not an abstract and overloading is an ad-hoc decision you should probably recoognise the child requires access to the parent's private property and declare it as "protected" instead...
Unless I'm totally missing your problem?
I think a lot of this topic is going to head the way of "developer preference", i.e. you could argue the merits of both options for weeks without reaching a concensus on which is "better". Personally I use getters/setters, mainly because I find them more readable, they encapsulate, and hell...they just look neater...
Besides, I often do a bit more than just return a property value. Getter/Setters make it easier to add additional steps related to fetching or setting a property value. For example if storing a database table row in an object I might want to track which values are changed, so I can determine what values need updating, or if an update is even necessary...
Posted: Mon Jan 16, 2006 10:51 am
by Jenk
Like you have also described, it's not a problem with the declaration itself, to further use the bankbalance example - what if the developer needs to overload the setter to, I dunno, verify the input is a float or validate the account number before setting etc.. thinking about it, it could be done like so:
Code: Select all
<?php
class BankAccount2 extends BankAccount
{
function setBalance ($balance)
{
if (strval(floatval($balance)) === strval($balance)) {
parent::setBalance($balance);
} else {
//error
}
}
}
?>
Actually, that looks like a good way of doing things.. but would that actually set the balance property of the object, or does parent::setBalance() call it statically?
This problem isn't really that evident in PHP, as to have the class you automatically have the source - though in another syntax it can be if the developer does not have the source to hand.
Posted: Mon Jan 16, 2006 2:28 pm
by raghavan20
I see there is no security in using use getters() and setters() if you do not use access specifiers before them. I do think PHP 4 should not be held as example.....please use PHP 5.
Even if you use setters, any other class member function() or any statement should be able to access the setter function, you must prohibit access directly to the setter instead it should go through some other member function which first validates a request for updating balance is valid. Please use examples with access specifiers, private, protected and public.
Posted: Mon Jan 16, 2006 5:48 pm
by Chris Corbyn
onion2k you say that it's not important now to do sanity checking on the properties... maybe it's not.
As the application this object structure resides in starts to grow I'd rather have that reassurance even when it's plain obvious... it's just good habit

Another point I wanted to mention was that I'll often start coding things on a basic level... then as the app builds up when $obj->foo changes form I also need $obj->bar reflect that change. Using accessor methods can save you a lot of time in the long run even if you didn't predict the need in the first place.
Hockey, as for the comment about not using
protected I agree with your pednantism when referring to properties in an object like that but when referring to class methods it works just the way it's intended...

Posted: Mon Jan 16, 2006 5:57 pm
by Jenk
does it bug anyone else that methods/properties are referred to as member functions/variables respectively in the php manual?
Posted: Mon Jan 16, 2006 6:43 pm
by Gambler
Yep. And it's not simply manual. Writing "private function" feels funny too.
Posted: Mon Jan 16, 2006 6:51 pm
by Chris Corbyn
Guys... even C++ books do that

"member function"... what's the harm, it's just another terminology, it's not incorrect

It's a function right? And it's a member of it's class.
Posted: Mon Jan 16, 2006 7:14 pm
by Jenk
I'm a Java fan boy, therefore it's method and property for me
btw - if anyone else is curious about the result of my previous question RE: parent::get() -
Code: Select all
<?php
class A
{
private $a = 1;
public function getA ($a)
{
$this->a = $a;
return $this->a;
}
}
class B extends A
{
public function getA ()
{
return parent::getA('a');
}
}
$b = new B;
echo $b->getA(); //outputs 'a'
?>
[EDITED ]
Posted: Mon Jan 16, 2006 8:06 pm
by raghavan20
Gambler wrote:Writing "private function" feels funny too.
can you explain in detail what you are trying to say?
I am a fan of Java as well. Calling functions as member functions and variables as member variables is more meaningful. It is good to have properties for a class. This is a good concept in Java and I do not know whether this exists from C++. In Java beans, you have to mandatorily declare getters() and setters() for properties. Properties are something like characteristics of a class object logically. The use of getters() and setters() simplifies the use of beans in JSP. The following two statements allows to set and get a property and it makes use of getFirstName() and setFirstName() to set the value and get the value respectively.
<jsp:setProperty name = 'memberBean' property = 'firstName' value = 'Fred' />
<jsp:getProperty name = 'memberBean' property = 'firstName' />