in reply to Dynamically Creating (and Calling) Object Methods

Almost there!

$myDB->{method1}->();

Note that you are adding these methods per *instance*, not to the whole class -- this is a technique used in prototype OOP. If you wanted to dynamically augment your class, the hash you need to edit is actually the BigDB package's symbol table.

Replies are listed 'Best First'.
Re^2: Dynamically Creating (and Calling) Object Methods
by zaven (Sexton) on Jan 07, 2007 at 09:16 UTC
    Thanks for the reply. That does make sense. After some googling I tried this approach in BigDB::new()...
    # $cmd = "method1" eval { no strict 'refs'; *{'BigDB\::$cmd'} = makeCommandSub($CMDS->{$cmd}); } or die "Can't modify the symbol table: $!";
    ...but this does not seem to result in a usable $myDB->method1() as I would like. ("Cannot locate method "method1" via package BigDB....")

    So next I tried hard-coding the new symbol name like so:

    *BigDB::method1 = makeCommandSub(...);
    and that works! So I just need to know how to use a string as part of the symbol reference. More clues? :-)
      First, unrelated to your main task: you don't need to say eval {...} or die $!, for several reasons. The first is that if it throws an exception, you can probably use the original exception :) Second, the or there is dangerous unless makeCommandsSub is guaranteed to return a true value; the valuation of an eval is (like any other block of Perl 5) its last evaluated thing. So
      eval { 0 } or die "this dies, but not because of an exception in the i +nner block!";

      Finally, $! is wrong in this case, you need $@ for the exception.

      But to your real question:

      You said 'BigDB\::$cmd'. But because of the single quotes, this creates literally a '$cmd' package in BigDB's symbol table! (Check by printing keys %BigDB::.) The correct code is

      *{"BigDB::$cmd"} = ...

      You probably got the backslash from code that used a variable containing the caller, where it's needed to make Perl not think you're talking about a fully qualified variable:

      *{"$caller\::methodname"} = ...
      'BigDB\::$cmd' is single-quoted, so creates a method named $cmd in package BigDB\ instead of a method named method1 in package BigDB. Try double quotes (where the backslash becomes harmless though unnecessary).