Recently I opened up one of my old college textbooks to see what would happen if I tried to implement some examples in Perl. When I ran across abstract classes, the gears in my head started to churn: "Why would Perl even need abstract classes?"

This question evently led me to question how much OOP I have written with Perl. Not much. As a matter of fact, whenever I did, it was not a serious endeavor.

Rather than question just how practical OOP is in Perl, I instead focus on abstract classes in Perl. Why do you need an abstract class in Perl?

First off. What is an abstract class?
don't answer that, it's a rhetorical question :)

An abstract class is class that is never meant to be instantiated, instead its existance is to provide a basis for other classes that will inherit from it. Java and C++ have reserved tokens for declaring abstract classes, but Perl does not. For that matter, Perl doesn't even have a 'class' reserved token (who needs it anyways). But that's okay, Perl is just following a path that has been accepted throughout the existance of modern day computers - if the 'hardware' can't do it, 'software' can and will be written to do it. Perl is just as capable of providing classes, abstract and concrete - it just might not be as 'pretty' as other languages.

Why are abstract classes even needed? What convience do they provide?

At first glance, the obvious answer is common functionality. For example, Java provides a toString() method that is defined in the Object class. Since all objects in Java are sub-classes of Object, they too have a toString() method. But Object is not an abstract class - you can create an Object class. Looks like common functionality is not the reason . . .

Rather than ask the question again - I will now jump straight to the point. When I said that an abstract class provides a common basis for other classes, I was not quite accurate, because a class does not have to be abstract to provide this basis. I should have instead said that an abstract class provides a common interface.

The textbook I was looking at was Design Patterns by qw(Gamma Helm Johnson Vlissides), by the way. Here is their answer to why abstract classes are a 'good thing' in a nut shell:

  1. classes do not depend upon the 'types' of objects and attributes
  2. classes are only bound to an interface
and I have to reprint their mantra - because it's a good one: Interfaces provide the ability to change the 'type' of an attribute within a particular class without breaking any clients that use that class. There is an old saying that goes something like this, "A function should never return a value, a function should return a pointer to a structure that contains a pointer to that value".

Now that is a bit extreme - but you will never have to worry about the 'type' of that value changing from a 'short' integer to a 'long' integer should scalability rear its ugly head.

But wait a second, Perl doesn't make the programmer worry about types - there are no 'floats' or 'double longs' - only scalars.

So, why does one need abstract classes in Perl? Also, are there any CPAN modules that use abstract classes?

UPDATE: Let me add to that last question:
"are there any CPAN modules that use abstract classes internally?" I will continue to look myself.

Thanks,
Jeff

R-R-R--R-R-R--R-R-R--R-R-R--R-R-R--
L-L--L-L--L-L--L-L--L-L--L-L--L-L--
  • Comment on Why do you need abstract classes in Perl?

Replies are listed 'Best First'.
Re: Why do you need abstract classes in Perl?
by merlyn (Sage) on Mar 05, 2001 at 03:28 UTC
    An abstract class gives the programmer a chance to inform the compiler that some derived classes share a common interface, and therefore can be used interchangably in some circumstances. You're right, Perl doesn't need that.

    But an abstract class gives the programmer a chance to inform the next programmer that some derived classes share a common interface, so that if a new derived class is added, the common methods are expected to be implemented. And, an abstract class can implement common behavior as well, even if it's never instantiated.

    -- Randal L. Schwartz, Perl hacker

Re (tilly) 1: Why do you need abstract classes in Perl?
by tilly (Archbishop) on Mar 05, 2001 at 03:32 UTC
Re: Why do you need abstract classes in Perl?
by dws (Chancellor) on Mar 05, 2001 at 07:38 UTC
    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.)

          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.

Re: Why do you need abstract classes in Perl?
by LD2 (Curate) on Mar 05, 2001 at 03:42 UTC
Re: Why do you need abstract classes in Perl?
by jplindstrom (Monsignor) on Mar 05, 2001 at 06:22 UTC
    Even if Perl doesn't "need" to indicate that a class is abstract, you may make the design decision that your class structure will contain one. So it isn't a question of syntax, but of OO design.

    And as with most other things related to OO Perl, you have to do it yourself :) I usually die with a helpful error message in abstract methods to inform the programmer that the method needs to be redefined.

    /J

Re: Why do you need abstract classes in Perl?
by jmcnamara (Monsignor) on Mar 05, 2001 at 13:53 UTC
    Let me add to that last question:
    "are there any CPAN modules that use abstract classes internally?"


    Spreadsheet::WriteExcel uses an abstract base class as the parent for a Workbook and a Worksheet class. There is a short description and a UML diagram here. In the section entitled "The Structure of the Module".

    John.
    --
    Something tells me we aren't programming in Pascal anymore, Toto.
      Ahhh, the BIFFwriter! And the irony: I started using Spreadsheet::WriteExcel just last week. Works like an absolute charm! Thanks John!

      Jeff

      R-R-R--R-R-R--R-R-R--R-R-R--R-R-R--
      L-L--L-L--L-L--L-L--L-L--L-L--L-L--
      
(tye)Re: Why do you need abstract classes in Perl?
by tye (Sage) on Mar 05, 2001 at 21:24 UTC

    "Abstract classes and Perl" just makes me chuckle. Like you said, abstract classes allow you to define an interface... And in Perl, that comes down to precisely "a few method names". Despite there being at least two implementations (metioned above by tilly) of abstract classes in Perl, I can't help but wonder whether the minimal value is worth the effort.

    Sure, using an abstract class in Perl prevents you from completely forgetting to implement one of the methods. It doesn't require that you even come close to using the same interface in the methods that share a name, because Perl has no useful, built-in tools for defining interfaces (prototypes are built-in but not useful for defining an interface and there are some modules that help you define an interface but they aren't built-in).

    Now, if your interface was defined via something like Class::Contract, then an abstract class might be a worthwhile thing.

            - tye (but my friends call me "Tye")

      I can't help but wonder whether the minimal value is worth the effort. Sure, using an abstract class in Perl prevents you from completely forgetting to implement one of the methods...

      This, by itself, can be enough.

      Take, for example, an online shop that sells several different types of items - each of which will be a class. It quite often makes sense here to ensure that each of these has all the methods that will be needed in the system to be able to buy the item - a title, price, SKU, whatever.

      Yes, you could just add it to your standards that anyone adding a new class of item must add these, and ensure that your reviewers look for this. But if you have an abstract class that all of these use, with an array of necessary types that you just add to any time you need to insist on a new abstract class method, then you don't need to do this. You just wait for the @ISA line to blow up!

      Tony

      Just to butt my $0.02 in...

      Doesn't perl provide one abstract class?
      package ("class") UNIVERSAL? it provides a basic set of interfaces: can(), isa(), and VERSION().
      Or am I confused (possible)?
      _________________
      madams@scc.net
      (__) (\/) /-------\/ / | 666 || * ||----||

        No, if UNIVERSAL were an abstract class, then the can() and isa() methods would be unimplemented (that is what makes a class abstract -- none of its methods are implemented, the class consists of only a interface definition and no implementation) and you would be required to implement them yourself in any class you build that inherits from UNIVERSAL (which would be all classes since all classes inherit from UNIVERSAL implicitly).

                - tye (but my friends call me "Tye")