Basically what I'm trying to achieve is to make the object reference another object of the same class - from inside of a method. It'd be perfect if the following would work:
$this = new self;
But one cannot reassign $this
in php.
I of course know, I can return another object from the method and use that, so please do not advise that. The question is:
How can I make $this
to be a clone of another object of the same class?
or more specifically,
I want an object to revert to a specific state that was previously saved.
EDIT: some examples where this might be useful.
Say you have an Url object that accepts controller, action and lots more things. You are going to have it fetch a lot of links with the same, say, controller and action, but other properties will differ. I instantiate the object with the common parameters, call a method for it to save its state which it reverts to after outputting a link (IOW after __toString method).
$defaultPath = Url::factory('controller','action1')->extraParams('status',0)->save();
echo $defaultPath->action('action2'); // this has action2 as action and a status 0 as extra params
echo $defaultPath->extraParams('status',2); // this has action1 as action and 2 as status
Another use is I have a CRUD table and I have to configure each colum开发者_高级运维n as an object I pass to the main table object. After passing the column I launch a reset method on the column, so I can have code like the following:
$column->field = 'layouts_id';
$column->value = $layoutId;
$dbInput->addColumn($column);
$column->field = 'pages_id';
$column->value = $pagesId;
$dbInput->addColumn($column);
In both situations I save a lot of code and confusion, don't you think?
I see a huge problem with what you're intending:
If you found a way to reassign $this
, how do you make sure, that anybody using your class knows how it behaves? While I admit, that it's kinda interesting to do
$column->field = 'layouts_id';
$column->value = $layoutId;
$dbInput->addColumn($column);
$column->field = 'pages_id';
$column->value = $pagesId;
$dbInput->addColumn($column);
What happens, if I need $column
twice?
$column->field = 'layouts_id';
$column->value = $layoutId;
$dbInput->addColumn($column);
// log my value
$logger->log($column); // oops, it's empty
...
You would break the expected behaviour and imho make it extremely hard to grasp your code.
But to give some ideas on how to still achieve the aforementioned behaviour:
// clone when passing on
$column->field = 'value_id';
$column->value = $value;
$dbInput->addColumn(clone $column);
// manually (re-)create a new object based on an older
$column->field = 'value_id';
$column->value = $value;
$dbInput->addColumn(new Column($column));
Otherwise the
reset()
method also sounds feasible:
class Column() {
public function reset() {
$this->field = 'standard field id';
$this->value = 'standard field value';
}
public function __construct() {
$this->reset();
}
}
This way you could use it like so:
// manually (re-)create a new object based on an older
$column->field = 'value_id';
$column->value = $value;
$dbInput->addColumn($column);
$column->reset();
To overcome the problem of specifying the default values twice (untested):
class Column() {
public $field = 'standard field id';
public $value = 'standard field value';
// keep a static object for resetting
private static $__blueprint = null;
public function reset() {
foreach (self :: $__blueprint as $k => $v)
$this->$k = $v;
}
public function __construct() {
if (!isset(self :: $__blueprint))
self :: $__blueprint = clone $this;
}
}
You cannot assign a value to $this
in PHP. It will always contain the current object, and that cannot be changed.
It sounds like you are trying to change all references to the current class to point to a different class. There is no way to accomplish this.
The best work around I can think of is to have a $copy
member variable in your class. You can then check if $copy
is not null and pass through all methods to that object instead. However, this will still leave you with your original object in memory.
if your hypothetical example $this = new self;
did work, it would presumably be intended to effectively reset the object to a clean state.
You can't achieve this the way you've asked, but you could surely do it fairly easily by writing a reset()
method that sets all the properties to their intial state and then calls the __constructor()
method.
If you want to go further and clone another instance of the class from within the object that would become the clone (as per the last part of your question), that'll be a lot harder. You certainly won't be able to do it in a nice way. You might be able to jury-rig it by writing a method that takes the object to be cloned as a parameter and sets all the current object's properties to the properties of the other object by reference. That would only be possible of course if all the properties were public, but you could try it. Certainly not ideal though. Far far better to simply do it from outside of either of the objects... but you did say not to suggest that... ;)
What you are asking doesn't make sense in OOP. The this
variable (or whatever its equivalent is in the OOP language of your choice) should always point to the current instance and should never be changed. That's whats it is designed for.
What I think you're getting at is basically the Flyweight Design Pattern. You don't do it by re-mapping $this
, but you create your objects in such a way that they can be re-used without needing to constantly construct and destruct them...
Couple that with the Object Pool Design pattern, and you should be golden...
精彩评论