... # Encapsulated class data my %_attr_data; # for each package: stores reference to its attribute data only my %_mro_cache; my %_attr_data_cache; # for each package stores reference to its attribute data + inherited attribute data # Class methods to operate on encapsulated class data sub _get_attr_data { my $caller = shift; my $package = ref($caller) || $caller; return %{$_attr_data_cache{$package}} if defined $_attr_data_cache{$package}; my @parents = @{ $_mro_cache{$package} ||= mro::get_linear_isa($package) }; my %return; for my $parent (@parents) { # assure that a reference is inside $_attr_data{$parent} ref $_attr_data{$parent} or next; for my $attr (keys %{$_attr_data{$parent}}) { $return{$attr} ||= $_attr_data{$parent}{$attr}; } } $_attr_data_cache{$package} = {%return}; return %return; } ...