package GenericObject; use strict; use warnings; use Carp; use Hash::Util qw/lock_keys lock_hash/; sub create { my $class = shift; $class = ref($class) || $class; my $prop_names = shift; my $method_names = shift; my $code_refs = shift; my (%properties, %methods); @properties{ @$prop_names } = map { '' } (0..$#$prop_names); lock_keys(%properties); @methods{ @$method_names } = @$code_refs; lock_hash(%methods); my $closure = sub { my $magick = shift; # first resolve any property sets or gets if (exists $properties{ $magick }) { $properties{ $magick } = shift if @_; return $properties{ $magick }; } # next resolve any method calls, making # sure to include a ref to the %properties hash elsif (exists $methods{ $magick }) { return &{ $methods{ $magick } }(\%properties, @_); } else { croak "Magick $magick not defined"; } }; return bless ($closure, $class); } sub incant { my $self = shift; return &{ $self }(@_); } 1; #file: test_object.pl #!/usr/local/bin/perl use strict; use warnings; use GenericObject; use Carp; my @props = qw/red green blue/; my @method = qw/getHexRGB print_colors init/; my @code_ref = (\&getHexRGB, \&print_colors, \&init); sub getHexRGB { my $props = shift; return sprintf("%02X%02X%02X", $props->{red}, $props->{green}, $props->{blue}); } sub init { my $props = shift; my %colors = @_; for (keys %$props) { $props->{$_} = $colors{$_}; } } sub print_colors { my $props = shift; print "\nColor table\n"; for (keys %$props) { print "Color $_\t\t", $props->{$_}, "\n"; } } my $genobj = GenericObject->create([@props], [@method], [@code_ref]); $genobj->incant('init', red=>19, green=>255, blue=>9); $genobj->incant('print_colors'); print "The colorref of \$genobj is\n", $genobj->incant('getHexRGB'), "\n"; print "\nChanging red to ", $genobj->incant('red', 55), "\n"; $genobj->incant('print_colors'); print "The colorref of \$genobj is\n", $genobj->incant('getHexRGB'), "\n";