package Person; use strict; use warnings; use Hash::Util::FieldHash qw(fieldhashes id); use overload '%{}' => \&_refsub, fallback => 1; fieldhashes \my(%given,%surname,%fullname); # package attribute 'fullname' tie $Person::fullname{Person}, 'Person::fullname', 'Person'; sub new { my $class = shift; my %args = @_; my $obj = bless do{ \my $x }, $class; for(qw{given surname}) { $obj->$_ = $args{$_} if $args{$_}; } tie $fullname{$obj}, 'Person::fullname', $obj; $obj; } # make getters/setters for (qw{given surname fullname}) { eval "sub $_ : lvalue { \$${_}{shift()} }"; } # provide $obj->{attribute} syntactic sugar - for more confusion # sub _refsub { # my $obj = shift; # warn "WARNING: dereferencing $obj as hashref is deprecated\n"; # warn "WARNING: setting an attribute via hashref does NOT work\n"; # { # given => $obj->given, # surname => $obj->surname, # fullname => $obj->fullname, # }; # } # tied interface for compound attribute 'fullname' package Person::fullname; sub TIESCALAR { my $class = shift; my $obj = shift; my $tied = bless \$obj, $class; } sub FETCH { my $obj = shift; join" ", grep {length} $$obj->given,$$obj->surname; } sub STORE { my $obj = shift; my ($first, $last) = split /\s+/,shift; $$obj->given = $first; $$obj->surname = $last; } 1;