http://qs1969.pair.com?node_id=342971


in reply to What is this can() and why is breaking it (un)acceptable?
in thread Why breaking can() is acceptable

Quite simply, all classes in perl inherit from UNIVERSAL. UNIVERSAL implements can. Your class then has an obligation (IMO of course) to provide a working version of can in its interface. If you break aspects of your base class in your subclass you are doing bad OO and defeating the whole purpose of re-use through inheritance.

-stvn

Replies are listed 'Best First'.
Re: Re: What is this can() and why is breaking it (un)acceptable?
by hardburn (Abbot) on Apr 06, 2004 at 16:58 UTC

    Your class then has an obligation (IMO of course) to provide a working version of can in its interface.

    If we are talking from an OO purity point of view, I would agree. Anything that breaks inheritance is evil and must be avoided.

    OTOH, a lot of people agree that multiple inheritance is needed in some cases, but there is no good way to implement it. How do you handle dimand inheritance? In what order do you call destructors (something that's been an issue on the Squawks of the Parrot blog of late)? There's no good answer, and an awful lot of bad ones.

    Abigail-II gave a great example in this thread of how easy it is to break inheirtance in Perl (one which I hadn't considered before). If you implement your class as a hashref, all your parents and subclasses also must use a hashref. Which might be the most common case, but it isn't the only one.

    Observation: this thread is a case study in why Perl's object system is hacked on.

    ----
    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

Re: What is this can() and why is breaking it (un)acceptable?
by jonadab (Parson) on Apr 07, 2004 at 04:00 UTC
    Quite simply, all classes in perl inherit from UNIVERSAL. UNIVERSAL implements can.

    This is an interesting statement. The index of my Camel book (2nd ed) does not list can at all and contains only one entry for UNIVERSAL, which points to page 293, where I find the following quote (emphasis mine):

    If neither a method nor an AUTOLOAD routine is found in @ISA, then one last, desperate try is made for the method (or an AUTOLOAD routine) in the special predefined class called UNIVERSAL. This package does not initially contain any definitions (although see CPAN for some), but you may place your "last-ditch" methods there.

    This not only doesn't support your assertion but seems on the face of it to directly contradict what you were saying. How can UNIVERSAL implement can, and require that all derived objects (i.e., all objects) not break that, if UNIVERSAL does not initially contain any definitions? Further, NOTHING is said here about any obligations that any module has to provide or support any particular method.

    Granted, what I have is not the latest edition, but none of the reviews I have read of the third edition have said anything about the new edition containing important information about fundamental changes to the language that every Perl programmer must know, nor is it advertised that way by the author or by the publisher. It's simply the next edition of the book, no more. I did see some reviews praising the addition of numerous new examples, but nothing that seemed to indicate to me that if I program according to the second edition I'll break things. To be perfectly honest, I've got a lot of things marked in my camel (not least, little tabs on the sides of the pages to mark where certain sections start so I can quickly flip e.g. to the section on special variables), and not wanting to redo all of that right away I was going to wait for the fourth edition, which hopefully will cover Perl6, before upgrading. Perhaps you could quote me just the paragraph of the 3rd edition that explains why every object is required to support the can method.

    update: In the light of morning, the next paragraph seems harsh to me. I didn't mean it that way. I'm not going to edit it out, though, because the reply wouldn't make (as much) sense then. (And chromatic, I recognize your reputation, but you hadn't yet come out to say anything in the thread when I wrote this.)

    I'm interested in hearing about the merits of can, the practical reasons why it's a useful thing for modules to support, even if the module author does not personally use it. I'm somewhat less interested in hearing you just tell me (in so many words) "This is just required". I might accept that coming from someone who is on a first-name basis with Larry's wife, but I am dubious as to what authority you have to make up requirements for all Perl modules to adhere to.


    ;$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$;[-1]->();print
      jonadab

      To start with, your Camel book is out of date, but thankfully, http://www.perldoc.com is not. Here is a link to the UNIVERSAL page. You may find this enlightening.

      As for my opinion (and I did make a point to say it was my opinion (note the "IMO")) about OO module designers obligations (please keep in mind it is specific to OO modules, as only blessed references inherit from UNIVERSAL). They are my opinions, you and the whole of the perl community have every right to dismiss them as the ravings of a lunatic (believe you wouldn't be the first).

      But my assertion that it is bad OO design to break the a method in your base class through some fault of your subclass, actually has nothing (directly) to do with Perl at all. It is just OO design, sure its maybe strict OO design, which Perl is certainly not known for, but if you pick up any (good) book on the subject, I am sure you will find something similar to what I say.

      -stvn
        your Camel book is out of date, but thankfully, http://www.perldoc.com is not.

        If I start using online docs, I'm going to end up wanting to keep every system up to date with the latest perl all the time. I was hoping to avoid that until Perl6 comes out. At present I use systems that have everything ranging from 5.005 through 5.6.1 to 5.8.1, and this has never proven to be a problem, not even when using a lot of modules off of the CPAN. I wouldn't want to start relying on all the latest features; that would be bad design for sure, and not only in terms of OO purity.

        In retrospect, my other post seems to have come across as a little harsh. For that I'm sorry. But I disagree that it's bad design to break something that's a fairly new feature anyway, within the same major version (Perl5).


        ;$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$;[-1]->();print