$obj->[0] = 'foo'; $obj->[1] = 'bar'; $obj->[2] = 'baz'; vs $obj->{'foo'} = 'foo'; $obj->{'bar'} = 'bar'; $obj->{'baz'} = 'baz'; #### package Class::Of::Obj; my $foo_idx = 0; my $bar_idx = 1; my $baz_idx = 2; $obj->[$foo_idx] = 'foo'; $obj->[$bar_idx] = 'bar'; $obj->[$baz_idx] = 'baz'; #### package Super::Class; my $foo_idx = 0; my $bar_idx = 1; my $baz_idx = 2; package Sub::Class; # err...now what? How do I start using the next open index? # Everything's hardwired up there and the Super::Class # isn't telling me. I'm stuck. #### package Super::Class; my $idx = 0; sub NEXT_IDX { return $idx++ }; use constant FOO_IDX => NEXT_IDX(); use constant BAR_IDX => FOO_IDX + 1; use constant BAZ_IDX => BAZ_IDX + 2; package Sub::Class; # need to wrap in BEGIN blocks so SUPER:: works in the use at # compile time. BEGIN {our @ISA = qw(Super::Class)}; use constant OTHER_IDX => __PACKAGE__>SUPER::NEXT_IDX(); # oops! NEXT_IDX() is still set to '0' up there, and we just set # OTHER_IDX to 1, clobbering whatever's in the BAR_IDX field! #### package Super::Class; use constant FOO_IDX => NEXT_IDX(); # 0 use constant BAR_IDX => NEXT_IDX(); # 1 use constant BAZ_IDX => NEXT_IDX(); # 2 package Sub::Class; # need to wrap in BEGIN blocks so SUPER:: works in the use at # compile time. BEGIN {our @ISA = qw(Super::Class)}; use constant OTHER_IDX => __PACKAGE__>SUPER::NEXT_IDX(); #now at 3, after BAZ_IDX #### package Super::Class; use constant FOO_IDX => NEXT_IDX(); # 0 use constant BAR_IDX => NEXT_IDX(); # 1 use constant BAZ_IDX => NEXT_IDX(); # 2 package Sub::Class; # need to wrap in BEGIN blocks so SUPER:: works in the use at # compile time. BEGIN {our @ISA = qw(Super::Class)}; use constant OTHER_IDX => __PACKAGE__>SUPER::NEXT_IDX(); #now at 3, after BAZ_IDX package Other::Sub::Class; BEGIN {our @ISA = qw(Super::Class)}; use constant DIFFERENT_IDX => __PACKAGE__>SUPER::NEXT_IDX(); #now at 4, after OTHER_IDX #### package Super::Class; use constant FOO_IDX => NEXT_IDX(); # 0 use constant BAR_IDX => NEXT_IDX(); # 1 use constant BAZ_IDX => NEXT_IDX(); # 2 package Other::Sub::Class; # need to wrap in BEGIN blocks so SUPER:: works in the use at # compile time. BEGIN {our @ISA = qw(Super::Class)}; use constant DIFFERENT_IDX => __PACKAGE__>SUPER::NEXT_IDX(); #now at 3, DIFFERENT THAN LAST TIME package Sub::Class; BEGIN {our @ISA = qw(Super::Class)}; use constant OTHER_IDX => __PACKAGE__>SUPER::NEXT_IDX(); #now at 4, DIFFERENT THAN LAST TIME! #### package Super::Class; my $class_indexes = {}; sub NEXT_IDX { my $class = shift; #if we have an index for this class, then return it if (defined $class_indexes->{$class}) { return ++$class_indexes->{$class}; } else { no strict 'refs'; my @isa = @{$class . "::ISA"}; #root class has no super my $idx = @isa ? $isa[0]->CURR_IDX() : -1; $class_indexes->{$class} = $idx + 1; return $class_indexes->{$class}; } } sub CURR_IDX { my $class = shift; return $class_indexes->{$class}; } use constant FOO_IDX => __PACKAGE__->NEXT_IDX(); # 0 use constant BAR_IDX => __PACKAGE__->NEXT_IDX(); # 1 use constant BAZ_IDX => __PACKAGE__->NEXT_IDX(); # 2 package Other::Sub::Class; BEGIN {our @ISA = qw(Super::Class)}; use constant DIFFERENT_IDX => __PACKAGE__->SUPER::NEXT_IDX(); #set to 3 package Sub::Class; BEGIN {our @ISA = qw(Super::Class)}; use constant OTHER_IDX => __PACKAGE__->SUPER::NEXT_IDX(); #also set to 3 #### package Distant::Sub::Class; our @ISA = qw(Sub::Class Other::Sub::Class); #both OTHER_IDX and DIFFERENT_IDX point to index 3. Whoops. #### package Super::Class; # now store a global class_idx in addition to the individual # indexes on each class my $class_idx = 0; sub NEXT_CLASS_IDX { return $class_idx++ }; my $class_indexes = {}; sub NEXT_IDX { my $class = shift; return $class_indexes->{$class}++; } use constant CLASS_IDX => __PACKAGE__->NEXT_CLASS_IDX(); use constant FOO_IDX => __PACKAGE__->NEXT_IDX(); # 0 use constant BAR_IDX => __PACKAGE__->NEXT_IDX(); # 1 use constant BAZ_IDX => __PACKAGE__->NEXT_IDX(); # 2 package Other::Sub::Class; BEGIN {our @ISA = qw(Super::Class)}; use constant CLASS_IDX => __PACKAGE__->NEXT_CLASS_IDX(); use constant DIFFERENT_IDX => __PACKAGE__->SUPER::NEXT_IDX(); #set to 0 package Sub::Class; BEGIN {our @ISA = qw(Super::Class)}; use constant CLASS_IDX => __PACKAGE__->NEXT_CLASS_IDX(); use constant OTHER_IDX => __PACKAGE__->SUPER::NEXT_IDX(); #also set to 0 #### my $obj = Sub::Class->new(); $obj->[CLASS_IDX]->[OTHER_IDX];