$ ./test.pl score: 0 vx: -1 symbol: _ #### shown: 1 score: 0 x: 0 vx: -1 y: 0 vy: 0 symbol: _ #### #!/usr/local/bin/perl package Object; use strict; sub new { my ($proto, %args) = @_; my $class = ref $proto || $proto; my $self = bless {}, $class; $self->init(\%args); return $self; } sub init { my ($self, $args) = @_; my $defaults=$self->defaults; if (ref($defaults)) { # This is technically Ok because you are getting # defualts from yourself and accordingly the key=>values # should be correct @{$self}{keys %$defaults}=@{$defaults}{keys %$defaults}; } # If %args are given to new(), use those instead # Unfortunately this is technically bad practice, as the # key=>values will not be coming from yourself (in an abstract sense) # accordingly you really should implement code to determine if # the passed keys are in the set of allowed keys. # one way to do this is to make method calls for all legal attributes # and then use the keyname as the methodname. If the arg is not legal # perl will throw a runtime error that the method is not found # leaving it as is is asking for hard to identify bugs. # something like this might be in order: # $self->$_($args->{$_}) foreach keys %$args; @{$self}{keys %$args}=@{$args}{keys %$args}; return $self; } 1; package Mover; #use Object; our @ISA = qw(Object); use strict; sub defaults { my $self=shift; my $defaults = { 'symbol' => '?', # override this in subclasses 'x' => 0, # x-coordinate 'y' => 0, # y-coordinate 'vx' => 0, # velocity in x-direction 'vy' => 0, # velocity in y-direction 'shown' => 1, # still alive? } } 1; package Player; #use Mover; use strict; our @ISA = qw(Mover); sub defaults { my $self=shift; my $defaults =$self->SUPER::defaults(); @{$defaults}{'symbol','score'}=('_',0); return $defaults; } 1; use strict; use warnings; #use Player; my $player = Player->new('vx' => -1); for (keys %$player) { print "$_: ", $player->{$_}, $/; } 1;