in reply to Re^2: Interfaces for the masses!
in thread Interfaces for the masses!

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'; ...

⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Replies are listed 'Best First'.
Re^4: Interfaces for the masses!
by Anonymous Monk on Mar 28, 2006 at 03:42 UTC
    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.

      Oh bravo for saying that. I wish I'd remembered to include all those caveats.

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊