in reply to Interfaces for the masses!

an interface is a class that defines a set of methods, without actually implementing any of them.

No, that's what Java thinks "interface" means. We have better things in perl. In fact, we have the freedom to define as much or as little of the that API (because that's really want you asked for). We can use subclassing, delegation, mixins, or anything else that fits our code.

[ Added You should look at the Dumper/Storable modules and things that implement freeze/thaw for examples of how perl has use interfaces successfully.]

Also, we already have two iterator interfaces: the tieable file handle and closures. I'd rather not see a "Class::Interface::Iterator" because I'm sure it's going to be more verbose and less useful than the tools we already have in common use.

[Updated: there was originally an interesting Freudian slip and I've removed it.]

⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Replies are listed 'Best First'.
Re^2: Interfaces for the masses!
by rvosa (Curate) on Mar 24, 2006 at 01:06 UTC
    No, that's what Java thinks "interface" means. We have better things in perl. In fact, we have the freedom to define as much or as little of the that API (because that's really want you asked for).
    I don't think that was quite what I asked for. The issue lies not so much in how much / little has been implemented, but that there could be scope for a contract such that $obj->isa('Interface'); tells you more than duck-typing based on a single method call could. Outside of implementation details. Isn't that a good idea under some circumstances, even if my understanding of what an interface is comes from Java?
    Added You should look at the Dumper/Storable modules and things that implement freeze/thaw for examples of how perl has use interfaces successfully.
    I just looked at Data::Dumper's and Storable's code. I don't see what you mean.
    Also, we already have two iterator interfaces: the tieable file handle and closures. I'd rather not see a "Class::Interface::Iterator" because I'm sure it's going to be more verbose and less useful than the tools we already have in common use.
    Okay, the iterator interface might be a bit over the top seeing that perl has wonderful list processing capabilities. But what about other patterns? I imagine general 'Model', 'View' and 'Controller' interfaces would be handy for the Maypole/Catalyst crowd?

      If you wrote UNIVERSAL::implements and made it take a contract name, you'd have what you want. I think I'm more likely to use Params::Validate to do my duck-type checking. Not that it's seemed all that important in practice. Occasionally I've needed ->can() and if the object has a method of the appropriate name, that's good enough. I've never seen an occasion where an object implements something wrong under the same name.

      Normal duck typing

      use Params::Validate 'validate_pos'; use constant FOOBAR_TYPE => { can => [ qw[ print flush frobnicate ] ] +}; sub bar { my $foobar = validate_pos( @_, FOOBAR_TYPE ); }

      Your stricter version.

      use Params::Validate 'validate_pos'; use constant FOOBAR_TYPE => { callbacks => { interface => sub { Interf +ace::has( FooBar => $_[0] ) } } }; sub bar { my $foobar = validate_pos( @_, FOOBAR_TYPE ); } package FooBar; use Interface 'FOOBAR'; ...

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

        But under no circumstances are you ever going to write a UNIVERSAL::something module because it corrupts every other module loaded and results in many people hating you.

        Me included.

        Every UNIVERSAL::foo module is a mistake, and a failure to solve a problem more elegantly.

        There's lots of modules that provide "standard" interfaces, like IO::Socket.

        And when I want to act like one, implement the needed methods and then add
        sub isa { $_[1] eq 'IO::Socket' ? 1 : shift->SUPER::isa(@_); }
        Which makes me ->isa('IO::Socket') without having to have thier implementations as my parent methods.