My code and explanation don't really stand alone. If the original traits paper is read, it makes more sense. If you're familiar with mixins, then traits can be loosely thought of as mixins that have conflicts explicitly resolved (thus eliminating the ordering problem of mixins). Also, unlike mixins (as I understand them), a trait may require certain methods (expectations) that it does not itself implement. Thus, if you have a polygon class and you want furry polygons (whatever that means), then you might use a "Furry" trait. That trait might expect a paint method, but not implement it directly. Instead, it expects that it will be provided once the traits are flattened into the primary class.
I see now that my description of interfaces was misleading. In Java, of course, an interface is merely a listing of methods that a class must implement. This is checked at compile time. For Class::Trait, I internally add methods to an "interface" and this interface is then validated when the Class::Trait->assemble method is called. Thus, if the "Furry" trait expects a paint method, this is added to the interface. The "interface" that I describe is dynamically generated and not validated until all required traits are examined. When assemble() is called, the methods are flattened and if a paint method is not found, the program dies, thus ensuring that, at the very least, the required methods are present (though there's no way in any language I know of to verify that those methods do what they should, though being able to specify method signatures would help).
| [reply] |
CHECK {
die unless __PACKAGE__ -> can ("paint");
}
except that the actually check is delayed till run time?
In that case, I'd rather see an interface like:
use Class:Trait qw /paint/;
with no explicite assemble call, but have
the checking done at compile time. That might be useful
if you write a module that are only useful if callbacks
are installed.
Abigail | [reply] [d/l] [select] |