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 */
?
Why not using Singleton for multiple objects with getInstance() ?
Andrey
Derrell.Lipman@UnwiredUniverse.com wrote:
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 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
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
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:
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 */
?
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
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
Lukas Smith 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.
--
Sebastian Bergmann http://www.sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69
Sebastian Bergmann wrote:
Lukas Smith 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.
Is there a way to reference constants from the same class (or dervived
class) in a friendlier way?
thanks for listening,
- Markus
Hello Markus,
Tuesday, May 10, 2005, 8:31:05 AM, you wrote:
Sebastian Bergmann wrote:
Lukas Smith 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.
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
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
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/
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
Sebastian Bergmann wrote:
Lukas Smith 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.
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 wrote:
Sebastian Bergmann wrote:
Lukas Smith 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.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
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)
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
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
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
2005/5/10, Sebastian Bergmann sb@sebastian-bergmann.de:
Lukas Smith 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.
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.
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:
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.
--
--
Best regards,
Marcus mailto:mail@marcus-boerger.de
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.
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
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.
My thoughts are:
-
Adding to many __methods is ugly.
-
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:
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 */
?
Hi,
Justin Hannus wrote:
My thoughts are:
- Adding to many __methods is ugly.
right
- 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
My thoughts are:
-
Adding to many __methods is ugly.
-
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:
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 */
?