This is not a question about real code, it is just for discussion. It looks to me that it would be nice to be able to pass an object as a constant reference.
$c = Coordinate;
unsafe_func($c); 开发者_StackOverflow社区// this should be ok
unsafe_func(... constant reference ... $c); // this should fail on write to $c
I know about an option to pass a clone of the object like set(clone $c)
which will keep my original $c
not modified by unsafe_func()
, but what if I would like to have a single object instance?
What I came up with is a wrapper class (code: https://gist.github.com/904897) using __set()
and __get()
magic methods, throwing exception on every __set()
call. It allows me to do this:
class CoordinateConst extends stdConst {};
unsafe_func(new CoordinateConst($c)); // exception: can not be modified!
What I do not like about the solution is that by introducing CoordinateConst, I have to remove Coordinate typehints. But if I extend Coordinate class, __set()
method is not called for visible properties.
The question: Is there a more common way to do this or would you rather avoid such code for any case (by passing object clone, wrapping unsafe_func call or something else)?
You solution effectively prevents public properties from being written to. The coordinate would not be a constant reference if it had a function such as:
public function setX($x) {
$this->x = $x;
}
An alternative (but more code depending on how often you want to do it), would be to create ReadOnly versions of the classes.
I know in Java and C# it's commonly applied to Collections. C# has a ReadOnlyCollection<T>
, which is just a wrapper/proxy, much like you have done there.
So my approach to the problem would be to create:
class ReadOnlyCoordinate {
private $coordinate;
public function __construct(Coordinate $coordinate) {
$this->coordinate = $coordinate;
}
public function getX() {
return $this->coordinate->getX();
}
Of course, you could extend Coordinate, and then throw Exceptions on functions that set any properties.
Then looking at the issue overall, if you don't want Coordinate members/setters to be exposed to unsafe_func
, then perhaps you could only send the required data. Which does of course depend on how much of the Coordinate data it requires.
e.g.
unsafe_func($coordinate->getRequiredData());
but then if you have a lot of data it requires, it would become a hassle.
精彩评论