Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Re^3: interface.pm explained

by Ovid (Cardinal)
on Aug 02, 2004 at 13:58 UTC ( [id://379285]=note: print w/replies, xml ) Need Help??


in reply to Re^2: interface.pm explained
in thread interface.pm explained

Since I'm new to this and haven't tried it out yet: can a class that consumes a trait override the code it receives from the trait?

Yes. I can simply choose not to import a particular method. Using Class::Trait syntax:

use Class::Trait some_trait => { exclude => [ "methods_I_dont_want" ] };

If you still need that code and don't want to exclude it, you can alias it to another name:

use Class::Trait some_trait => { alias => { old_name => 'new_name' } };

Apart from moving them to deterministic compile-time, how do traits help resolve ordering problems associated with MI?

Let's say that you have a class which inherits from both a Bomb class and a GirlFriend class.

package SomeThingOrOther; use base qw/GirlFriend Bomb/; ...

(I realize you understand the ordering problem. I explain the following for the benefit of those who might be reading and not know.) Your class needs to explode() from Bomb, but unbeknownst to you, the GirlFriend class also has an explode() method! Now, because you used GirlFriend first in your use base ... statement, you get the wrong behavior and this can be very difficult to debug. Of course, if there's another duplicate method in your two base classes but you don't want the one in your Bomb class, you're life gets even more difficult. Now you need to use delegation or start hard coding classnames, neither of which is quite as easy as simply inheriting the data was supposed to be.

Traits make this a trivial problem:

use Class::Trait GirlFriend => { exclude => [ "explode" ] }; use Class::Trait Bomb => { exclude => [ "some_method_in_girlfriend" ] };

Suppose I have class Base that uses traits. Then along comes class Child. Where does it get its traits from?

The Child class should not know or care about where Base gets its methods. Are they traits or implemented directly? It should not matter. All Child needs to know is the published interface to Base. That's when the Child class can decide whether or not to override Base methods. Whether this is done through writing the methods directly or use of traits should not matter at this point.

One final comment: some of my code snippets above can look daunting to those unfamiliar with traits. In reality, most traits are pretty straightforward.

use Class::Trait 'TPrintable'; use Class::Trait 'TId';

Hope this helps!

Cheers,
Ovid

New address of my CGI Course.

Replies are listed 'Best First'.
What Java does
by gaal (Parson) on Aug 02, 2004 at 19:37 UTC
    My interest was piqued, so I had to see what Java does when your class implements two interfaces with "conflicting" function signatures. (They're not strongly conflicting since there's no code that's competing like in MI.)

    Curiously, the following code compiles cleanly without even a warning — at least on Eclipse 3.0 with the default warning settings (and I couldn't find anything to change there that might be relevant).

    It's curous to me not because I don't see why this works. It's obvious that it *can* work. But interface clash means a design problem, and I'd expect this to at least warrant a warning.

Possible problem in Class::Trait
by gaal (Parson) on Aug 02, 2004 at 19:14 UTC

    The Child class should not know or care about where Base gets its methods.

    Then there is problematic behavior in Class::Trait. Not sure if this is exactly a bug or a design contention, but the following is inconsistent with your point above. Quoting the docs:

      If a method label in a class conflicts with a method label in the trait (or composite trait), the class method is chosen and the trait method is discarded. This only applies to methods defined directly in the class's symbol table, methods inherited from a base class are overridden by the trait method.
    Since a trait inherited from Base is not flat (mixed in) in Child, overriding behavior is different.

    IMHO the default behavior for conflicts (of any sort) should be a fatal compile time error. If you don't do this you lose a significant advantage of protocols (using the more theoretic term here to distance from Java interfaces). If you think that this is wrong, at least make the behavior consistent. ("You" ne you personally, necessarily; I realize somebody else is maintaining the module now.)

      Actually, I think we see this from a different point of view as I don't think this behavior is inconsistent. Let's say I have an Animal class, a subclass of Organism. In this class I use an Eat trait (Insect might use this, too, for example), but since the author of Organism decided (for the sake of argument) that not all living things eat, there is no &eat method to inherit. A trait might be appropriate here because I don't want to redefine the method (which I would have to do with interfaces) and there's nothing else to logically inherit from. Further, delegating this to another class might not make a lot of sense.

      So now I decide that I want a Mammal class which inherits from Animal. If I want to override &Animal::eat, I need to explicitly code &Mammal::eat. Explicitly coding this should mean that I really, really want what I coded. Whether or not &Animal::eat came from a Trait or was hand-coded should be irrelevant to my desire to override it. I should not care about implementation details. Therefore, regardless of whether I hand-coded &Mammal::eat or got it from a Trait, this method should behave towards inherited methods exactly the same way. If I have a Trait method that overrides an inherited method, I as the programmer have the responsibility to know the published interfaces of the Classes and Traits that I use. On the other hand, an optional warning might be nice; I'll have to think about that.

      Does that make sense? I'm not sure I explained that well.

      Cheers,
      Ovid

      New address of my CGI Course.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://379285]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2024-04-16 20:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found