Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

chromatic (983)

chromatic
  (email not shown publicly)
http://wgz.org/chromatic/

Blog Information [technorati.com] Profile for chr0matic [technorati.com]

Journal of chromatic (983)

Thursday February 09, 2006
03:39 PM

Why would a class override isa()?

[ #28641 ]

In a comment on my UNIVERSAL::can module, someone asked "Why would a class override isa()?"

Easy. Suppose your code is paranoid about the objects it receives to certain methods. You want to make sure that you don't call invalid methods on invalid invocants.

That's fine. That's good. You don't want your code to break.

Of course, you're totally fine breaking my code. What if I look carefully at the interface and behavior you require from such an object and write a proxy object that does absolutely everything right? There are lots of reasons to do this -- caching, autouse trampolines, testing with Test::MockObject, logging, debugging.

If I don't override isa() in my class, your code vomits messily even if my object does exactly what your code needs it to do because all you care about is that the object you receive inherits from some base class. Yippee. You broke my code for no good reason.

That's why Perl 6 has roles and suggests that does() is the question you should ask of a potential invocant instead of isa(). That's why you can override isa() in Perl 5.

If your code doesn't allow that (say -- if you use UNIVERSAL::isa() as a function, not a method), your code is broken and wrong. Please fix it.

(Still don't believe me? Go break your own code for a change: download Acme::UNIVERSAL::new and replace all of your constructor calls with calls to UNIVERSAL::new(). If that doesn't make the problem abundantly clear, I don't know what else to say.)

Update: removed a clause that may have given offense. I apologize to everyone who read the previous version.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • chromatic, I was with you, thinking "right on!", until the last paragraph. Then you blew it. I think you owe an apology to the highly talented, dedicated and prolific programmer you referred to in the first paragraph.
    • Maybe so, but I'm tired of explaining this issue to every person who files a bug report against one of my modules when the problem is that other people break my code by writing buggy code.

      I'm very tired of explaining why this is a problem and what the fix is and being ignored, mocked, disbelieved, and blamed for it.

      If, after all of that, someone can't look at Acme::UNIVERSAL::new and see why that doesn't work and realize that the exact same problem applies to UNIVERSAL::isa() and UNIVERSAL::new(), I don

      • chromatic,

        It took me a while to come around to your point of view and I think it's taking others a while too. The problem is that the buildin isa() and can() die on non-blessed objects and most people (me included) didn't think it was OK to wrap it in an eval{}. For me, I believed the dogma that eval"" is slow and bad and transferred that to eval{}.

        Unfortunately, I believe that UNIVERSAL::{can,isa}.pm are fanning the flames more than strictly necessary. Yes, they *have* succeeded in getting people to tal
        • Without the warnings, I'm not sure people would have found and reported the bugs they did, but I do understand your point about the tone of the documentation in UNIVERSAL::isa.

          I'm not sure what to say about the broken code other than that it's broken though. Ideally I wouldn't need to use these modules in Test::MockObject.

        • While I find their _tone_ overly confrontational in the docs, having UNIVERSAL::(isa|can) silently work around is the second worst possible solution (the worst being that they die or something).

          There ARE cases for using UNIVERSAL::isa and and can directly, but they are few and far between and you really need to know what you are doing.

          Personally, I think I've used it in CPAN module maybe a total of 6 times where you could change a UNIVERSAL::isa call ->isa and expect it to be correct. In 99% of cases you
          • ugh... I need to wake up more...

            That should read,

            "Personally, I think I've used them in a CPAN module maybe a total of 6 times where you couldn't change a UNIVERSAL::isa call ->isa and expect it to be correct. In 99% of cases you SHOULD be calling the it as a method (or using Params::Util::_INSTANCE for the DWIM approach).