in reply to Request for review: OO, inheritance, and a symbol table trick.

One additional thing to be aware of is that not all of the code entries you find in the symbol table will be methods of the class/object. That is, somebody could just put in a helper function in the package that you can't call as an object method.

That is, you could have stuff like this in the child package:

package SimpleExample; sub method_foo { my $self = shift; # ... bla bla bla ... my $arg = 42; my $intermediate_result = helper_function($arg); # ... bla bla bla ... } # ... sub helper_function { my ($arg) = @_; # ... bla bla bla ... }

Now guess what a simple symbol table scan will give you: you will get out both "method_foo" and "helper_function" as code entries in the symbol table. But you can't say SimpleExample->helper_function($bar). "helper_function" is just a normal function, not a method.

Solution: you will have to test any function names you got from the symbol table of the package if they can be called on the class/object. You do that by using the much underestimated "can()" method from package UNIVERSAL.

Ah, and before I forget it: obviously you will have to do a recursive symbol table scan to get all the methods for a given package, scanning the parents of a class/object as well.

Here is how something similar is done in Test::Unit::TestCase, part of the Test::Unit framework (coded by brother pdcawley, thanks again Piers!).

sub list_tests { my $class = ref($_[0]) || $_[0]; my @tests; no strict 'refs'; if (defined(@{"$class\::TESTS"})) { push @tests, @{"$class\::TESTS"}; } else { push @tests, grep { /^test/ && $class->can($_) } keys %{"$class\::"}; } push @tests, map {$_->can('list_tests') ? $_->list_tests : ()} @{"$class\::ISA"}; my %tests = map {$_ => ''} @tests if @tests; return keys %tests; }

(And yes, I have been there and messed it up. Thanks to Piers Cawley for educating me.)

Christian Lemburg
Brainbench MVP for Perl
http://www.brainbench.com