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

I want to recursively access class variable in a series of classes, like this:

use strict; package Base; our %types = qw/BASE_TYPE Some::Class/; sub get_type {} package Foo; our @ISA = qw/Base/; our %types = qw/FOO_TYPE Another::Class/; package Bar; our @ISA = qw/Base/; our %types = qw/BAR_TYPE Yet::Another::Class/; # what I want: # get: BASE_TYPE => Some::Class, # FOO_TYPE => Another::Class my %foo_type = Foo->get_type(); # get: BASE_TYPE => Some::Class, # BAR_TYPE => Yet::Another::Class my %bar_type = Bar->get_type();

What I actually want is to simulate the sugar in actionscript's EventDispatcher, which can register type string with classes of event object, and derived dispatcher own all registered things from its parents recursively.

Replies are listed 'Best First'.
Re: How to implement such kind of magic?
by BrowserUk (Patriarch) on Dec 02, 2009 at 10:02 UTC

    Something like this?

    package Base; our %types = qw/BASE_TYPE Some::Class/; sub get_type { return %types; } package Foo; our @ISA = qw/Base/; our %types = qw/FOO_TYPE Another::Class/; sub get_type { return ( Foo->SUPER::get_type(), %types ); } package Bar; our @ISA = qw/Base/; our %types = qw/BAR_TYPE Yet::Another::Class/; sub get_type { return ( Bar->SUPER::get_type(), %types ); } package main; use Data::Dump qw[ pp ]; my %foo_type = Foo->get_type(); pp \%foo_type; my %bar_type = Bar->get_type(); pp \%bar_type; __END__ c:\test>junk3 { BASE_TYPE => "Some::Class", FOO_TYPE => "Another::Class" } { BAR_TYPE => "Yet::Another::Class", BASE_TYPE => "Some::Class" }

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: How to implement such kind of magic?
by moritz (Cardinal) on Dec 02, 2009 at 10:05 UTC
    I don't quite understand what you want. Should each class have its own %types hash, but somehow fall back to the parent's hash if something is not found? If yes, that can be implemented with methods and SUPER:: calls.

    Or do you want one hash in the base class, and populate it along the way? That might look like this:

    use strict; use warnings; { package Base; our %types = qw/BASE_TYPE Some::Class/; sub get_type { $types{$_[0]} } } { package Foo; our @ISA = qw/Base/; $Base::types{FOO_TYPE} = q/Another::Class/; } { package Bar; our @ISA = qw/Base/; $Base::types{BAR_TYPE} = q/Yet::Another::Class/; } use Data::Dumper; print Dumper \%Base::types; print Base::get_type('BAR_TYPE'), $/;
      I want to have only ONE function exists in the root class, and it seems only one OUR variable exists in the root class is not a good solution, because it will be affected by all of its descendants. What I want is:
      Foo: get Base and Foo Bar: get Base and Bar
      but not:
      Foo: get Base, Foo and Bar Bar: get Base, Foo and Bar
      It seems that I have to write a sub recursively traverse through the namespace tree?