New issue 22 by kenshaw: Annotations do not support inheritance
http://code.google.com/p/addendum/issues/detail?id=22
What steps will reproduce the problem?
/** Target('class') */
class AAA extends Annotation { }
/** Target('property') */
class BBB extends Annotation { }
/** @AAA('no') */
class x {
/** @BBB('no') */
public $my_var;
}
class y extends x { }
$obj = new y();
$reflection = new ReflectionAnnotatedClass($obj);
echo "Are Annotations inherited
>> ".((int)$reflection->hasAnnotation('AAA'));
What is the expected output? What do you see instead?
Expected:
Are Annotations inherited >> 1
Instead:
Are Annotations inherited >> 0
What version of the product are you using? On what operating system?
svn HEAD on Debian
Please provide any additional information below.
I would be willing to write it (it seems extremely simple to implement) if
given SVN access.
I think you should be able to annotate Annotations with another special one
like target like this:
/**
@Target('class')
@Inheritable(true)
*/
class AAA extends Annotation { }
You could then toggle the inheritance of the attribute per method,
property, or class. It would be simply some updates to the internal.
Hi, could you please add a real world use case why do you need something
like this? Just curious.
When you have a large set of objects that inherit from a common class and
don't want to recreate the Annotations on each inherited object. Or if you
have a hierarchy of objects and want to set it on the tree.
In C#, with attributes, you can toggle the inheritance of the attribute.
Ok, but could you please be more specific? I am yet to be convinced about a
real world usage of inheritable annotations.
It's not a big problem, but I would love to see what you are doing in real
world.
I can't (unfortunately) put in specific code at this time, but it is
something like this:
/** @Default('value') */
class Element {
final public function getDefault() {
// use annotated default value if there is no default value set
// (ie, via a setDefault or via the constructor or some such)
$reflection = new ReflectionAnnotatedClass($this);
if (!isset($this->params['default']) &&
$reflection->hasAnnotation('DefaultValue')) {
return $reflection->getAnnotation('DefaultValue')->value;
}
return $this->params['default'];
}
}
class ElementName extends Element { }
/** @DefaultValue('new default value') */
class SomeOtherElement extends ElementName { }
Note that ElementName doesn't get a DefaultValue annotation -- it should
inherit that from the parent class (if that annotation is inheritable).
Basically I don't want to redefine the DefaultValue (and many other things
that I'm defining with Annotations in a class heirarchy). So something that
is understood by a final function in a parent class. I'm using this in a
combination of a Template Method design pattern and a Strategy pattern for
encapsulating things such as Regular Expression validators etc.
(please excuse the example above. I wrote it extremely quickly).
Hmm, this seems like not only inheritance, but also as a kind
of "overloading" behavior.
What bothers me, now is what will happen if you have multiple valued
annotation a you try to overload/inherit only some of the attributes. What
is the desired behavior?
Could you send your specific code via email? (jo...@jsmf.net) I am really
curious.
Overloading would work the same as regular object oriented overloading. Say
you had Class A, B, and C, where B inherits from A, and C inherits from B,
then Annotation overloading would work the same. For instance, if class B
overloads Annotations from class A, then class C would inherit the
annotations from class B.
I will try to send you some specific examples, but its just mainly for
setting default values in an element hierarchy. This is useful in
producing/consuming very complex XML documents that represent such things.
Also, since I seem to have you on the line -- what would you think of
adding getTypeHint() for parameters to functions/methods? Eventually PHP
will include it in the language (its in trunk/ it's just not in 5.3 or 5.2
-- see http://ilia.ws/archives/207-Type-Hinting-Conclusion.html). As
stop-gap measure, it would sure make things a bit easier for me ;) Heh.