Hi,
Specifying the accessor methods in an interface reveals too much of
the implementation. Properties (the kind with accessor methods) are
themselves an abstract concept. You want to be able to take an
interface definition such as:interface foo {
public $bar; // if you prefer this to abstract $foo;
}and implement it like this:
class DoIt implements foo {
public $bar;
}or to implement it using setters, using your notation:
class DoIt2 implements foo {
public $foo {
public function get();
protected function set($value);
}
}The whole point of this kind of property is that the caller is never
supposed to know if they are just accessing a object instance variable
or an accessor method. This is called the uniform access principle.
http://en.wikipedia.org/wiki/Uniform_access_principle
I like this concept, so I extended it and wrote some code
("SimplePDO") showing my ideas. You can see it here:
http://internals.php.pastebin.com/f6a3cc2f
This way, every property can have 0 - 6 functions, that change methods
of accessing it:
void load() // (made for simple lazy-loading)
typeof(property) get()
void validate(mixed $value) throws InvalidValueException
typeof(property) set(typeof(property) $value)
bool isset()
void unset()
They are called in this way:
PHP code:
echo $object->property;
What PHP does behind the scenes (in PHP-based pseudocode, somebody
will have to write it in C for Zend Engine):
$object = $object;
$property = 'property';
if (!property_is_readable($object->$property))
{
throw new PropertyNotReadableException($object, $property)
}
if (is_null($object->$property.realValue))
{
try
{
$object->$property.load();
}
catch (UndefinedPropertyMethodException $e) {}
}
try
{
return $object->$property.get();
}
catch (UndefinedPropertyMethodException $e)
{
return $object->$property.realValue;
}
PHP code:
$object->property = 'new value';
What PHP does behind the scenes:
$object = $object;
$property = 'property';
$newValue = 'new value';
if (!property_is_writable($object->$property))
{
throw new PropertyNotWritableException($object, $property)
}
try
{
$object->$property.validate($newValue);
}
catch (UndefinedPropertyMethodException $e) {}
/* Does not catch InvalidValueException */
try
{
return $object->$property.set($newValue);
}
catch (UndefinedPropertyMethodException $e)
{
return $object->$property.realValue = $newValue;
}
PHP code:
isset($object->property);
What PHP does behind the scenes:
$object = $object;
$property = 'property';
if (!property_is_readable($object->$property))
{
return false;
}
try
{
return $object->$property.isset();
}
catch (UndefinedPropertyMethodException $e)
{
return (is_null($object->$property.realValue)) ? false : true;
}
PHP code:
unset($object->property);
What PHP does behind the scenes:
$object = $object;
$property = 'property';
if (!property_is_writable($object->$property))
{
throw new PropertyNotWritableException($object, $property)
}
try
{
$object->$property.unset();
}
catch (UndefinedPropertyMethodException $e)
{
try
{
$object->$property.set(null);
}
catch (UndefinedPropertyMethodException $e)
{
$object->$property.realValue = null;
}
}
property_is_readable() and property_is_writable() language constructs
check if property is readable/writable in current context.