Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Re: Inheritance: the root of the problem

by stvn (Monsignor)
on Aug 04, 2006 at 17:15 UTC ( #565707=note: print w/ replies, xml ) Need Help??

in reply to Inheritance: the root of the problem

As sort of an academic exercise, I've been thinking about how one could re-envision Perl's object model using closures as objects, without using the bless() function (because otherwise, of course, that's not really re-envisioning Perl's object model — it's just modifying it slightly).

Well, one problem is that bless() and packages are the way in which Perl does it's method dispatching. Without hacking the core of Perl and making the method dispatching more "hookable", you will find that you will end up jumping through many syntactic hoops to make things work (or using AUTOLOAD which pretty much rules it out as a tool for "serious" use).

As a quick aside, you might want to take a look at something I did while working on the Perl 6 metamodel for Pugs, it was a small prototype metamodel based on one written in Scheme. It is basically closure based objects like you suggest, with a slight layer of "sugar" to make them a little more Perl 5 friendly.

Now, I will skip the rest of your post and go right to the updated question.

What are the fundamental problems inheritance is meant to solve, and how can we solve them in relation to a closure-based object model for Perl 5.x?

My first suggestion is to read read read. There are many people thinking about such things, and much time, effort and research has been put into trying to answer this question and then solve it. Here is a quick list of some good resources:

  • Traits

    The people who gave us Traits have done a *lot* of thinking on this subjects, I recommend reading pretty much all the papers on this page. They do a decent job of breaking down the problems of inheritance and show traits as a solution (this and this do a good job of illustrating the real world benefits of their proposed solution).

  • Scala

    The Scala language is an excellent resource for cutting edge OO thinking, in particular with how it can be merged with learnings from functional languages. Some interesting bits of Scala are: Case Classes, Traits and a very nice mixin mechanism. While they still support the traditional OO inheritance model, it has been shown how it's trait and mixin mechanism can be used to solve The Expression problem which traditionally is very messy to solve with inheritance.

  • Slate

    Slate is a prototype-based OO language based on Self, CLOS, Smalltalk with some Dylan mixed in for good measure. It takes an interesting approach in that it's objects are constructed in a prototype-ish fashion, but method dispatch is done with MMD (Multi-Method Dispatch). They demonstrate this as being a very powerful feature in their examples.

  • CLOS

    CLOS (like most things LISP) has been on the cutting edge for about the past 20 years. It's predecesors such as Flavors were invented in the early 80s and are still cutting edge by todays (watered down Java/C++/C#/etc.) standards. The Art of the MetaObject Protocol, which describes the CLOS object model in great depth, is, IMHO, a classic and still relevant today despite having been written in 1991 (lets see how useful all those C# books are 15 years from now).

  • Dylan

    Dylan has been described as "CLOS with an Algol like syntax", which is fairly accurate, but does not really convey the whole picture. Dylan is an extremely powerful language which is sadly fallen into obscurity. Just poking around the reference manual should give you an idea of how totally cool Dylan is :)

  • Scheme

    I don't have any good links for this one, but since Scheme does not come with it's own object model, it has sort of become a right of passage for CompSci PhD types to write their own object models (kind of like what templating systems are for Perl). Simply googling for "Scheme Object Models" will give you tons of stuff, both good and bad.

  • AOP

    AOP (Aspect Oriented Programming) was a big Java buzzword a few years ago, and seems to have lost some of it's steam lately. The idea was that there are some "concerns" which are "cross-cutting" and so therefore do not follow the "direction" of inheritence. There is some merit to this of course, but AspectJ (the sort of de-facto standard in AOP) was basically a compiler pre-processor, and so not truely hooked into the object model itself. It is not suprising that Gregor Kiczales, one of the key figures of the CLOS spec, was also of the fathers of AOP. The metamodel in CLOS basically can do all that AOP can do, and IMHO do it much better. But alas, Java has no programmer accessible metamodel so a compiler preprocessor it was, *sigh*.

  • And lastly, a plug for Moose and Class::MOP

    These are my modules which I have written because I was tired of dreaming of all the nice Perl 6 OO features and having to write crappy Perl 5 OO for $work. They are not (as you are proposing) a re-invention of OO as we know it, but instead a metamodel atop the current Perl 5 OO which should enable much meta-level experimentation. They are heavily based on my study of CLOS and Smalltalk among other things (most of which is mentioned above). It may not be directly relevant to what you are suggesting, but i figure it is worth mentioning at least.

Now, onto your question.

Inheritance is not really a bad thing when used appropriately. Some things are really best described with an single inheritence is-a relationship. However, other things are not so simply strutured. But once multiple inheritence comes into the picture, inheritence becomes a really nasty thing. This is where mixins, traits and roles come in with their "sets of behaviors" which can be "injected" into a class (I tend to think of inheritence as being a vertical thing, while (mixin|trait|role)s are a horizontal thing).

From a not-really-OO-but-kinda-like-OO perspective, there is the Standard ML module system and Haskell's TypeClasses. Here is a link to a fairly well received paper comparing the two, but I have to admit I have not read it yet so I cannot vouch for it. Both these systems take a very "first-class" view of modular units, and create very powerful (and sometimes mind-bendingly complex) systems with it.

I see all of these things as attempting to solve the basic problem of modular composition, or to phrase it as a question; "How to compose behaviors and state together in a highly reusable fashion?". I think inheritence is simply one part of the solution (albeit a very overused/abused one), and should not be tossed out because it really does have it's place. If properly used, along with other tools such as (roles|traits), mixins and generics, it is a good thing.

Anyway, lunch break is over, time to get back to $work. Enjoy the links.

Comment on Re: Inheritance: the root of the problem

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://565707]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (10)
As of 2016-05-27 06:10 GMT
Find Nodes?
    Voting Booth?