new overloading feature?

php.internals

Unnamed Person

21 years ago
I came across an interesting desire today. I'd like to create a new class instance if an only if a "key" value does not already exist. This key value could be looked up in a database, in an array, etc. The following contrived example shows use of a proposed __new() overload function which would be called BEFORE the constructor, and could chose to return a newly constructed object (by calling __construct()) or to return an already existing object. One could certainly call a function which searched for the key value and only instantiated a new object if the existing one was not found, but this seems cleaner. Thoughts? <?php class X { static $allX = array(); var $val; function __construct($val) { $this->val = $val; X::$allX[] =& $this; } function __new($val) { foreach (X::$allX as $x) { if ($x->val == $val) { return $x; } } return __construct($val); } } $try1 = new X(23); /* would return $allX[0] reference */ $try2 = new X(42); /* woudl return $allX[1] reference */ $try3 = new X(23); /* would return $allX[0] reference */ ?>

Andrey Hristov

21 years ago
Why not using Singleton for multiple objects with getInstance() ? Andrey Derrell.Lipman@UnwiredUniverse.com wrote:

Unnamed Person

21 years ago
Andrey Hristov <php@hristov.com> writes:
> Why not using Singleton for multiple objects with getInstance() ?
Yeah, it's not quite a Singleton pattern. I've seen references to what I'm talking about as a Pool pattern. That's basically what I described here:
>> One could certainly call a function which searched for the key value and >> only instantiated a new object if the existing one was not found, but this >> seems cleaner.
There are absolutely ways to do this purely at the application level. It just seems that it'd be a really clean, easy to program, easy to understand methodology to pass the key value to the request for a new instance, and get back either a new instance, or a previously existing one with that key value. In fact, the proposed __new() feature could provide an automatic Singleton capability without the caller needing to worry about (or even know) that it's dealing with a Singleton. The class defines a __new() function that always returns its one and only instance (instantiating it the very first time), and the application can always use 'new' without worrying about the internal implementation. Derrell

Andrey Hristov

21 years ago
Derrell.Lipman@UnwiredUniverse.com wrote:
> Andrey Hristov <php@hristov.com> writes: > > >> Why not using Singleton for multiple objects with getInstance() ? > > > Yeah, it's not quite a Singleton pattern. I've seen references to what I'm > talking about as a Pool pattern. That's basically what I described here: >
Yes, Pool. I just said that it is Singleton for multiple objects which in fact is pool.
>>>One could certainly call a function which searched for the key value and >>>only instantiated a new object if the existing one was not found, but this >>>seems cleaner. > > > There are absolutely ways to do this purely at the application level. It just > seems that it'd be a really clean, easy to program, easy to understand > methodology to pass the key value to the request for a new instance, and get > back either a new instance, or a previously existing one with that key value. > > In fact, the proposed __new() feature could provide an automatic Singleton > capability without the caller needing to worry about (or even know) that it's > dealing with a Singleton. The class defines a __new() function that always > returns its one and only instance (instantiating it the very first time), and > the application can always use 'new' without worrying about the internal > implementation. > > Derrell >
The thing I find nice in the current way of implementing it with getInstance() and a static class variable is that it is like it is defined in GoF. People can easily understand what's going on. Otherwise it is too much of magic to me:) Andrey

Andi Gutmans

21 years ago
At 06:14 PM 11/5/2004 +0100, Andrey Hristov wrote: The thing I find nice in the current way of implementing it with getInstance()
>and a static class variable is that it is like it is defined in GoF. People >can easily understand what's going on. Otherwise it is too much of magic >to me:)
Agree and PHP 5 gives enough tools to do this on your own. Personally I find such overloading a disadvantage rather than an advantage as it leads to less readable and more cryptic code. Verbosity is your friend... Andi

Unnamed Person

21 years ago
Derrell.Lipman@UnwiredUniverse.com writes: Leonardo Pedretti <lpedretti@suserver.com> writes:
> I would like (for code cleanliness purposes) to make 'new' return a > reference to an already created object under certain circumstances without > using a factory, is it possible?
A number of months ago, I proposed a similar feature, implemented as overloading a __new() function. At the time, it seemed I was the only one who wanted it, but your request is for a feature identical to my request. Here's my previous message. (The whole thread can be found under the subject "new overloading feature?" from 5 Nov 2004). I'd love for this to be revisited now that there's someone else with a similar desire. My previous proposal:

George Schlossnagle

21 years ago
Derrell.Lipman@UnwiredUniverse.com wrote:
>Derrell.Lipman@UnwiredUniverse.com writes: > >Leonardo Pedretti <lpedretti@suserver.com> writes: > > > >>I would like (for code cleanliness purposes) to make 'new' return a >>reference to an already created object under certain circumstances without >>using a factory, is it possible? >> >> > >A number of months ago, I proposed a similar feature, implemented as >overloading a __new() function. At the time, it seemed I was the only one who >wanted it, but your request is for a feature identical to my request. Here's >my previous message. (The whole thread can be found under the subject "new >overloading feature?" from 5 Nov 2004). I'd love for this to be revisited now >that there's someone else with a similar desire. > >
I'm not an OO expert, but doesn't this break a fundamental semantic of OOP -- namely that new() returns a new object of the specified class. Isn't this the whole reason that the Singleton pattern exists? George

Lukas Smith

21 years ago
George Schlossnagle wrote:
> I'm not an OO expert, but doesn't this break a fundamental semantic of > OOP -- namely that new() returns a new object of the specified class. > Isn't this the whole reason that the Singleton pattern exists?
yeah I would agree that we should always try to find a non magic solution and in this case a singleton seems to be the obvious choice. however currently its kinda hard to write a singleton that will work even if you inherit from the base class that implements the singleton due to: http://bugs.php.net/bug.php?id=30235 regards, Lukas

Sebastian Bergmann

21 years ago
Lukas Smith wrote:
> http://bugs.php.net/bug.php?id=30235
I agree with Marcus: self is bound at runtime, so the behaviour is correct. If you do not like this late binding just do not use self but the name of the class.
-- Sebastian Bergmann http://www.sebastian-bergmann.de/ GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69

Markus Fischer

21 years ago
Sebastian Bergmann wrote:
> Lukas Smith wrote: > >>http://bugs.php.net/bug.php?id=30235 > > > I agree with Marcus: self is bound at runtime, so the behaviour is > correct. If you do not like this late binding just do not use self but > the name of the class.
Sorry to jump in the middle, but I've similiar question to constants defined in classes. When the class is named SomeLongNameBecauseWedontHaveNamespaces and I define a SELF_EXPLAINING_CONSTANT_NUMBER_ONE I've to write SomeLongNameBecauseWedontHaveNamespaces::SELF_EXPLAINING_CONSTANT_NUMBER_ONE to access it from within the class itself. Is there a way to reference constants from the same class (or dervived class) in a friendlier way? thanks for listening, - Markus

Marcus Boerger

21 years ago
Hello Markus, Tuesday, May 10, 2005, 8:31:05 AM, you wrote:
> Sebastian Bergmann wrote: >> Lukas Smith wrote: >> >>>http://bugs.php.net/bug.php?id=30235 >> >> >> I agree with Marcus: self is bound at runtime, so the behaviour is >> correct. If you do not like this late binding just do not use self but >> the name of the class.
> Sorry to jump in the middle, but I've similiar question to constants > defined in classes.
> When the class is named SomeLongNameBecauseWedontHaveNamespaces and I > define a SELF_EXPLAINING_CONSTANT_NUMBER_ONE I've to write > SomeLongNameBecauseWedontHaveNamespaces::SELF_EXPLAINING_CONSTANT_NUMBER_ONE > to access it from within the class itself.
> Is there a way to reference constants from the same class (or dervived > class) in a friendlier way?
We're not going to change the language for that, sorry.
-- Best regards, Marcus mailto:mail@marcus-boerger.de

Markus Fischer

21 years ago
Marcus Boerger wrote:
>>> I agree with Marcus: self is bound at runtime, so the behaviour is >>> correct. If you do not like this late binding just do not use self but >>> the name of the class. > >>Sorry to jump in the middle, but I've similiar question to constants >>defined in classes. > > >>When the class is named SomeLongNameBecauseWedontHaveNamespaces and I >>define a SELF_EXPLAINING_CONSTANT_NUMBER_ONE I've to write >>SomeLongNameBecauseWedontHaveNamespaces::SELF_EXPLAINING_CONSTANT_NUMBER_ONE >>to access it from within the class itself. > > We're not going to change the language for that, sorry.
I didn't request any change ;) Just wanted to know if there's a current better practice. If not, then not. thanks, - Mar'k'us

Jason Sweat

21 years ago
On 5/10/05, Markus Fischer <markus@fischer.name> wrote:
> When the class is named SomeLongNameBecauseWedontHaveNamespaces and I > define a SELF_EXPLAINING_CONSTANT_NUMBER_ONE I've to write > SomeLongNameBecauseWedontHaveNamespaces::SELF_EXPLAINING_CONSTANT_NUMBER_ONE > to access it from within the class itself. > > Is there a way to reference constants from the same class (or dervived > class) in a friendlier way?
Hi Markus, I often use self::SELF_EXPLAINING_CONSTANT_NUMBER_ONE when in context of a class method itself. HTH Regards, Jason http://blog.casey-sweat.us/

Markus Fischer

21 years ago
Jason Sweat wrote:
>>When the class is named SomeLongNameBecauseWedontHaveNamespaces and I >>define a SELF_EXPLAINING_CONSTANT_NUMBER_ONE I've to write >>SomeLongNameBecauseWedontHaveNamespaces::SELF_EXPLAINING_CONSTANT_NUMBER_ONE >>to access it from within the class itself. >> >>Is there a way to reference constants from the same class (or dervived >>class) in a friendlier way? > > I often use self::SELF_EXPLAINING_CONSTANT_NUMBER_ONE when in context > of a class method itself.
I forgot to add that I mean in static methods .. but thanks, - Markus

Lukas Smith

21 years ago
Sebastian Bergmann wrote:
> Lukas Smith wrote: > >>http://bugs.php.net/bug.php?id=30235 > > > I agree with Marcus: self is bound at runtime, so the behaviour is > correct. If you do not like this late binding just do not use self but > the name of the class.
So please explain to me how you would write a singleton static method for a base class from which you can inherite. Suddenly the idea with using the class name becomes less useful. The late binding seems to be a nice performance tweak, but it means that in many situations you end up having to do cut and paste in combination with inheritance. Doesnt seem very OOP to me, altough I fear Java behaves the same way. So all I am asking for is an easy way to call a static method in the current context (without having to go through the reflection API, having to store the class name in a static property etc). regards, Lukas

Lukas Smith

21 years ago
Lukas Smith wrote:
> Sebastian Bergmann wrote: > >> Lukas Smith wrote: >> >>> http://bugs.php.net/bug.php?id=30235 >> >> >> >> I agree with Marcus: self is bound at runtime, so the behaviour is >> correct. If you do not like this late binding just do not use self but >> the name of the class. > > > So please explain to me how you would write a singleton static method > for a base class from which you can inherite. Suddenly the idea with > using the class name becomes less useful. > > The late binding seems to be a nice performance tweak, but it means that > in many situations you end up having to do cut and paste in combination > with inheritance. Doesnt seem very OOP to me, altough I fear Java > behaves the same way. So all I am asking for is an easy way to call a > static method in the current context (without having to go through the > reflection API, having to store the class name in a static property etc).
Johannes reminded me that I should probably also mention this weekly news item on the topic: http://www.zend.com/zend/week/week219.php#Heading5 regards, Lukas

Ondrej Ivanič

21 years ago
Lukas Smith wrote:
> So please explain to me how you would write a singleton static method > for a base class from which you can inherite. Suddenly the idea with > using the class name becomes less useful.
IMHO, you need singleton factory :) Inheritance is very strong relationship between classes. For example I have base class 'Animal' and derived classes 'Dog' and 'Cat'. I can find similarity between 'Dog' and 'Cat'. (They are animals) If I have base class Singleton and derived classes 'MyCar' and 'MyCat'. I can't find similarity between this classes. Solutions is: class SingletonFactory { private $instances; __construct() { $this->instances = array(); } function getInstance($name) { if(is_a($this->instances[$name], $name) === false) { $this->instances[$name] = new $name; } return $this->instances[$name]; } } FYI: SingletonFactory can be a pure static class.
-- Ondrej Ivanic (ondrej@kmit.sk)

Lukas Smith

21 years ago
Ondrej Ivanič wrote:
> class SingletonFactory { > private $instances; > > __construct() { > $this->instances = array(); > } > > function getInstance($name) { > if(is_a($this->instances[$name], $name) === false) { > $this->instances[$name] = new $name; > } > > return $this->instances[$name]; > } > } > > FYI: SingletonFactory can be a pure static class. >
yes it just doesnt work if you normally already use a factory ..because then you cant do $name::factory(); regards, Lukas

Thomas Richter

21 years ago
Lukas Smith wrote:
>> FYI: SingletonFactory can be a pure static class. >> > > yes it just doesnt work if you normally already use a factory ..because > then you cant do $name::factory();
call_user_func(array($name,"Factory")); ?? thomas

Lukas Smith

21 years ago
Thomas Richter wrote:
> Lukas Smith wrote: > >>> FYI: SingletonFactory can be a pure static class. >>> >> >> yes it just doesnt work if you normally already use a factory >> ..because then you cant do $name::factory(); > > > call_user_func(array($name,"Factory")); ??
that works if you store the class name for every child of the parent class into a static property. the problem is that unless you copy paste, maintain the class name in a static property for every child class you have a problem. both options seem to be rather clumsy and un-OOP. so it would be nice to have some way of getting the class name that is being called upon statically. regards, Lukas

Alex Knaub

21 years ago
2005/5/10, Sebastian Bergmann <sb@sebastian-bergmann.de>:
> Lukas Smith wrote: > > http://bugs.php.net/bug.php?id=30235 > > I agree with Marcus: self is bound at runtime, so the behaviour is > correct. If you do not like this late binding just do not use self but > the name of the class.
I don't agree with Marcus. Singleton or the name of the class are ugly workarounds for this bug. Every genuine OOP and dynamic language (ObjC, Ruby, Smalltalk) bounds self at runtime.

Marcus Boerger

21 years ago
Hello Alex, but PHP is a class based langauage which is very much different from prototype based langauages. Apart from that i already said that it would be possible to add a special 'called_self' (or better name) syntax to support what you want - only that would slow doen execution even if you won't use it. And since what you want is not the correct way of doing it in a class based language i don't think we should add it. regards marcus Tuesday, May 10, 2005, 6:33:55 PM, you wrote:
> 2005/5/10, Sebastian Bergmann <sb@sebastian-bergmann.de>: >> Lukas Smith wrote: >> > http://bugs.php.net/bug.php?id=30235 >> >> I agree with Marcus: self is bound at runtime, so the behaviour is >> correct. If you do not like this late binding just do not use self but >> the name of the class.
> I don't agree with Marcus. Singleton or the name of the class are ugly > workarounds for this bug. Every genuine OOP and dynamic language > (ObjC, Ruby, Smalltalk) bounds self at runtime.
> -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php
-- Best regards, Marcus mailto:mail@marcus-boerger.de

Alex Knaub

21 years ago
2005/5/12, Marcus Boerger <mail@marcus-boerger.de>:
> Hello Alex, > > but PHP is a class based langauage which is very much different from
what is a class based language?
> prototype based langauages. Apart from that i already said that it would be > possible to add a special 'called_self' (or better name) syntax to support > what you want - only that would slow doen execution even if you won't use > it. And since what you want is not the correct way of doing it in a class
that is the only correct way to use factories in a dynamic language, everything else leads to code duplication and / or crapy code.

Marcus Boerger

21 years ago
Hello Alex, Friday, May 13, 2005, 5:18:43 PM, you wrote:
> 2005/5/12, Marcus Boerger <mail@marcus-boerger.de>: >> Hello Alex, >> >> but PHP is a class based langauage which is very much different from
> what is a class based language?
It means the language is based around the idea that all objects refer to a certain class and you cannot dynamically add, change or remove members (though php allows to dynamically add properties).
>> prototype based langauages. Apart from that i already said that it would be >> possible to add a special 'called_self' (or better name) syntax to support >> what you want - only that would slow doen execution even if you won't use >> it. And since what you want is not the correct way of doing it in a class
> that is the only correct way to use factories in a dynamic language, > everything else > leads to code duplication and / or crapy code.
Yes but for php supporting this would means that we'd need to make php slower. And where is the problem in a little code duplication? Maybe you want templates? Maybe you're in the wrong language.
-- Best regards, Marcus mailto:mail@marcus-boerger.de

Alex Knaub

21 years ago
Hello Marcus, 2005/5/13, Marcus Boerger <mail@marcus-boerger.de>:
> > what is a class based language? > > It means the language is based around the idea that all objects refer to a > certain class and you cannot dynamically add, change or remove members > (though php allows to dynamically add properties).
ok, this makes the hole thing clearer. Now i understand the idea behind the php object model. thank you.

Justin Hannus

21 years ago
My thoughts are: 1. Adding to many __methods is ugly. 2. Interesting subject though. Not to add to the flame but I've seen the need for more advanced overloading features in allot of the code I've been writing with PHP5. Consider the following example (C++ almost like, may slow down the engine but seems like a cleaner idea): class StringObject { public $val = ''; public function __construct($str = '') { $this->val = $str; } public function __operator($operator, &$lOperand, &$rOperand, &$returnValue) { switch ($operator) { case T_CONCAT_EQUALS: if ($rOperand instanceof StringObject && $lOperand instanceof StringObject) { $returnValue = $lOperand->val . $rOperand->val; // or something? return true; // use operator handler; } // ...other operators that are supported by this object // can be defined here... } return false; // normal operation takes place; } } $str1 = new StringObject("hello "); $str2 = new StringObject("world!"); str1 .= $str2; This would be very useful and very clean but seems like if defined would really slow down the engine. But, i think this could work well in many, many different situations. Maybe only a subset of operators are overloadable with this method. -Justin Derrell Lipman wrote:

Johannes Schlueter

21 years ago
Hi, Justin Hannus wrote:
> My thoughts are: > > 1. Adding to many __methods is ugly.
right
> 2. Interesting subject though. Not to add to the flame but I've seen the > need for more advanced overloading features in allot of the code I've > been writing with PHP5. Consider the following example (C++ almost like, > may slow down the engine but seems like a cleaner idea):
NO. :-) Overloading operators had been discussed before a lot. Please check the archives and Steph's nice summaries: http://www.zend.com/zend/week/week210.php#Heading7 http://www.zend.com/zend/week/week222.php#Heading2 johannes
-- Johannes Schlüter Mayflower GmbH / ThinkPHP http://thinkphp.de http://blog.thinkphp.de

Justin Hannus

21 years ago
My thoughts are: 1. Adding to many __methods is ugly. 2. Interesting subject though. Not to add to the flame but I've seen the need for more advanced overloading features in allot of the code I've been writing with PHP5. Consider the following example (C++ almost like, may slow down the engine but seems like a cleaner idea): class StringObject { public $val = ''; public function __construct($str = '') { $this->val = $str; } public function __operator($operator, &$lOperand, &$rOperand, &$returnValue) { switch ($operator) { case T_CONCAT_EQUALS: if ($rOperand instanceof StringObject && $lOperand instanceof StringObject) { $returnValue = $lOperand->val . $rOperand->val; // or something? return true; // use operator handler; } // ...other operators that are supported by this object // can be defined here... } return false; // normal operation takes place; } } $str1 = new StringObject("hello "); $str2 = new StringObject("world!"); str1 .= $str2; This would be very useful and very clean but seems like if defined would really slow down the engine. But, i think this could work well in many, many different situations. Maybe only a subset of operators are overloadable with this method. -Justin Derrell Lipman wrote: