dragonchild has asked for the wisdom of the Perl Monks concerning the following question:

I need to be able to call a function in a parent class, but I can't guarantee that the parent class will have that function. So, I've got something like:

my $class = ref($self); foreach my $parent (@{"${class}::ISA"}) { my $value = $parent->do_something if $parent->can('do_something'); }

This is a class method, not an object method, so it takes a class-name as the first arg. From what I've read about can(), it only handles blessed references.

Replies are listed 'Best First'.
Re: UNIVERSAL::can() doesn't do what I need ...
by Vynce (Friar) on Jun 14, 2001 at 18:18 UTC

    actually, while the method itself might insist on a class name rather than an object, can() won't know that. so $self->can('do_something'); will correctly determine whether or not you can do it.

    your situation is made messier if you need to know which of its parents can do it; but that's OK, because you can call ->can() on a string that is the name of a class. Here's a one-liner to prove it.

    perl -e 'package It; sub doit{return pop}; $foo="It"; print($foo->can( +"doit")?"y":"n")'

    incidentally, i would recommend re-writing the method so that, if given an object rather than a class name, it gets the class name by ref'ing the object. e.g.,

    sub class_method { my $proto = shift; $class = ref($proto) || $proto; # do stuff ... }
    because there is almost never a reason not to.

    .

    update (about perldoc UNIVERSAL: yes, I saw that too; and i almost let it stop me from trying. But then i tried it anyway.

    and it is OK to doubt me, brother; doubt builds faith, and besides, i am only a man, after all

    .
      I do have the my $class_name = ref($self) || $self; at the top of the function. The thing is that, after the first call to do_something() (which passes an object), I'm solely going to be passing in the class name of the parent. This means that I needed to be able to do a can() on a string, which you say I can.

      Incidentally, the perldoc for UNIVERSAL::can() says that unless the first parameter is a bless'ed reference, it will return undef. I'm not doubting you, but the perldoc then is wrong. :(

Re: UNIVERSAL::can() doesn't do what I need ...
by lestrrat (Deacon) on Jun 14, 2001 at 18:09 UTC

    I think you can do

    UNIVERSAL::can( 'pkgname', 'subname' );