in reply to Why do you need abstract classes in Perl?

Here's a thought on implementing "abstract" classes in Perl, should you decide that you want to.

One thing that distinguishes an "abstract" class from a concrete one is that you shouldn't create instances the abstract class. There's no need for special syntax for this. You need merely do something like:

package AbstactFoo; ... sub new { die "Don't create any Abstract Foos direct, fool!"; }
And then rely on subclasses to implement their own new. Unfortunately, this confounds the common (and useful) idiom of inheriting new from a (possibly abstract) superclass.
package AbstractFoo; ... sub new { my $package = shift; bless { @_ }, $package; } ... my $foo1 = new SubclassOfAbstractFoo(); # GOOD my $foo2 = new AbstractFoo(); # BAD
Here's a way to get the benifit of an "abstract" new while still keeping the class abstract:
package AbstractFoo; ... sub new { my $package = shift; die "Don't subclass AbstractFoo directly!" if $package eq "AbstractFoo"; bless { @_ }, $package; }

(Bonus points to whoever sees a way to generalize this even further.)

Replies are listed 'Best First'.
Re: Re: Why do you need abstract classes in Perl?
by merlyn (Sage) on Mar 05, 2001 at 07:52 UTC
        package AbstractFoo; 
       ... 
        sub new { 
            my $package = shift; 
            die "Don't subclass AbstractFoo directly!" 
               if $package eq "AbstractFoo"; 
            bless { @_ }, $package; 
        }

    (Bonus points to whoever sees a way to generalize this even further.)

    sub new { die "this is an abstract subclass" if $_[0] eq __PACKAGE__; shift->SUPER::new(@_); }

    -- Randal L. Schwartz, Perl hacker

      Next time I'll limit the bonus points to Monks or below :)

      The use of __PACKAGE__ was what I was looking for. I was thinking along the lines of

      package AbstractFoo; ... sub new { my $package = shift; die __PACKAGE __ . " is an abstract class" if $package eq __PACKAGE__; bless { @_ }, $package; }

      merlyn and I had a back and forth in the CB about the difference between his solution and mine. I noted that his would fail if nobody in AbstractFoo's superclass chain implemented new. merlyn agreed, saying (and here I'll ask him to correct me if I get the details wrong) that this was correct behavior, given that there's no generic way to implement new. I granted that point, but cited the Smalltalk image as evidence that there were common patterns. That, in essense, is where we left the discussion.

        I think that's close to what I said. The problem is that there's no common "base class" for Perl objects as there is in the Smalltalk image, so you might want a hashref, or you might want an arrayref, or even a coderef. If the SUPER call fails, it's the right thing to have happen. Perhaps I could have put in a ->can and die call, but really, that's all the runtime system is going to do anyway. {grin}

        I will continue to argue that your bless is no more correct here than my die. It's really a personal framework choice.

        -- Randal L. Schwartz, Perl hacker