Page 1 of 1

Inheriting static methods/properties

Posted: Tue Jun 05, 2007 6:13 pm
by routinet
feyd | Please use

Code: Select all

,

Code: Select all

and [syntax="..."] tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read:  [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]


I've read the discussion on this,  but I just think it's wrong.  In the example below, the only you'll see "bar" is if both commented sections are uncommented, which keeps the context completely in class b.  I understand the reasoning behind the behavior.  At the same time, this behavior ignores the concept of reusability.  I'd have to reproduce all of my class a code in class b for 'proper' behavior, which negates the reason for having class a to begin with.  Is there any reconciliation for this?  Last I heard, "this behavior is expected and will not be fixed"...

Code: Select all

<?
class a {
	protected static $var1 = "foo";
	protected static function doit() {
		echo("in a:doit = " . self::$var1) . "<br>";
	}
	public function go() {
		self::doit();
	}
}

class b extends a {
	protected static $var1 = "bar";

/*
// commented section 1
	protected static function doit() {
		echo("in b:doit = " . self::$var1);
	}
*/

/*
// commented section 2
	public function go() {
		self::doit();
	}
*/

}

$d = New a;
$e = New b;
$d->go();
$e->go();
?>

feyd | Please use

Code: Select all

,

Code: Select all

and [syntax="..."] tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read:  [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]

Posted: Tue Jun 05, 2007 6:27 pm
by feyd
No you wouldn't. That's what constructors are for.

Posted: Tue Jun 05, 2007 7:03 pm
by routinet
Please elaborate. How would a constructor allow for the behavior I want to see?

Posted: Tue Jun 05, 2007 7:11 pm
by feyd
Setting of the previously established static. Just as the previously established static could, and likely should, in fact be set in a constructor as well.

Posted: Wed Jun 06, 2007 4:29 am
by stereofrog
The problem is that unlike $this, "self" binds early, and means "class, the method is declared in", not "the class, the method is called for". There was a plan to add a new keyword in php6 to support the latter behaviour. Till then, there's not much you can do about that. However, statics are just a fancy form of globals, perhaps the best option would be to avoid them altogether.

Posted: Wed Jun 06, 2007 5:27 am
by dbevfat
I believe the new keyword stereofrog is referring to will be static; it will refer to the class that uses it, not the class that declares it.

As for the comparison with globals, static variables are only global within the context of a class (and objects of that class) -- they have a limited scope which is not, in fact, truly global. This differs them from the ordinary globals (including singletons) that are truly global in terms of visibility and accessibility.

Posted: Wed Jun 06, 2007 2:37 pm
by routinet
@feyd:
Setting of the previously established static.
I understand what you're getting at, but that would require me to init the static before every call to any class extending the base parent. I have a single parent extended into multiple classes. One of the static variables I'm using controls the table used by whichever child class is operating at the moment. If I use the class constructor to set the static, that works fine for the first call. Subsequent calls may not work as intended because OTHER child classes have since been initialized, thus changing the parent class's static value. Your suggestion necessitates me managing those static values over and over again, in every child method that utilizes a parent static method or variable.

@stereofrog:
The problem is that unlike $this, "self" binds early, and means "class, the method is declared in", not "the class, the method is called for"
That seems completely counter-intuitive to me. I understand early vs. late binding, but I do not see how the actual implementation is justified. Say I have uncommented only block 2 from my original post. When I reference 'self' from public function go() in class b, I am obviously referring to the scope of class b. There's no way someone just reading that code would think I wanted to reference the scope of class a. But that's exactly what the code does. In this example, I'm calling self from within the class I want to use, and the scope is reverting back to the parent.

I see the point as far as static being bound to the defining class. My point is that by extending a class to form a new one, those inherited statics should be bound to the new extension. I am essentially saying "Take everything in this class here, and pretend I typed it in this class over here so that I don't actually have to", which is how I always understood class extension and inheritance to work.

To put it another way, if I have to reproduce all the work from my parent class inside the child class, what is the purpose of having the parent? This behavior destroys the concept of inheritance.

Posted: Wed Jun 06, 2007 5:03 pm
by kyberfabrikken
routinet wrote: To put it another way, if I have to reproduce all the work from my parent class inside the child class, what is the purpose of having the parent? This behavior destroys the concept of inheritance.
Yes, but it's a moot point, since there are very few situations where static members are a good solution anyway. Simply create an instance, and use that.