Buddha Buck <[EMAIL PROTECTED]> writes:

> At 08:13 AM 9/15/00 +1100, Damian Conway wrote:
> >Piers wrote:
> >
> >    > I'm kind of tempted to look at adding another pragma to go with 'use
> >    > base' along the lines of:
> >    >
> >    >      use implements 'Interface';
> >    >
> >    > Which is almost entirely like C<use base 'Interface'> but with
> >    > 'Interface' consisting of nothing but:
> >    >
> >    >
> >    >      package Interface;
> >    >
> >    >      sub virtual_method;
> >    >      sub virtual_method2 (#prototype);
> >    >
> >    >      ...
> >    >
> >    >      1;
> >
> >You and I must have been separated at birth, Piers.
> >
> >Here's what I wrote to Nat just yesterday:
> >
> 
> <snip>
> 
> 
> >         Interfaces might also act like pure abstract base classes when
> >         inherited, so that:
> >
> >                 package Dog;
> >                 use base 'Fetcher';
> >
> >         would cause a compile-time error if Dog failed to actually provide
> >         a C<fetch> method.
> 
> I don't like that at all...
> 
> Currently, Object implementations can be changed at will at runtime.  In 
> particular, it is possible to create new methods and change the class 
> hierarchy at run time.
> 
> package TextFilter;
> use CryptInterface;
> @ISA = qw(CryptInterface);
> 
> sub AUTOLOAD {
>    my $self = shift;
>    ($name = $AUTOLOAD) =~ s/.*://;
>    # Cryptography is very hairy and we don't want to load it if we don't
>    # have to.
>    if ($name = any(qw(setkey setcrypt encode decode)) {
>       require Crypt;
>       import Crypt;
>       push @ISA,"Crypt";
>       $self->$name(@_);  # I've not tried this, it may be wrong.
>    }
> }
> 
> I'd hate to have that break because TextFilter isn't derived from Crypt 
> unless it needs to be.

That's kind of scary. What's wrong with:

    use CryptInterface;
    @ISA qw(CryptInterface Crypt);

    sub AUTOLOAD {
        my $self = shift;
        $name = $AUTOLOAD =~ s/.*://;
        # Delay load of the Crypt package.
        if ($name = any(qw(setkey setcrypt encode decode))) {
            require Crypt;
            $self->$name(@_);
        }
    }

That way CryptInterface is always a Crypt, but doesn't load Crypt
until it needs to. Of course, there's still the compiletime breakage
issue. Maybe something like:

    use interface CryptInterface;
    use deferred qw/setkey setcrypt encode decode/;

BTW, I would argue that any 'compile time' errors that may get thrown
be the interface pragma should be in CHECK blocks. Hmm... you know,
it's probably possible to implement an interface pragma in perl as we
know it. I'll get back to you.

> I think calling a method declared in an inherited interface but not
> implemented would be a good reason to have a descriptive run-time
> error, like:
> 
> Method getkey in interface Crypt not implemented in TextFilter object at 
> line....
> 
> Well, perhaps written better...

Certainly should be *at least* a runtime error. I'm inclined to think
that, because we are adding this stuff to the language that there's no
harm in making 'em throw compiletime errors, so long as we can make it
easy to fix.

-- 
Piers


Reply via email to