package Soldier; use constant NAME => 0; use constant RANK => 1; use constant SERIAL => 2; sub new { my $class = shift; $class = ref($class) || $class; my $self = [ "", "Private", 000 ]; bless($self, $class); return $self; } sub name { my $self = shift; if (@_) { $self->[NAME] = shift; } return $self->[NAME]; } # similar methods for RANK and SERIAL
Any cryptographic implementation would do -- in fact, one could extend this class to use a different technique, if desires. Simply add an encrypt() method, and call that in new() and verify().package Password; use Digest::MD5 qw(md5_base64); # based on an idea by jbontje sub new { my $class = shift; $class = ref($class) || $class; my $self = shift; # takes a cleartext string for the passwo +rd $self = md5_base64($self); bless($self, $class); return $self; } sub verify { my $self = shift; my $candidate = shift; return ($self eq md5_base64($candidate)); }
package WordMatch; sub new { my $class = shift; $class = ref($class) || $class; my $word = shift; # word to match my $self = qr/\[$word\]/; bless($self, $class); return $self; } sub match { my $self = shift; my $string = shift; return $string =~ $self ? "Matches!" : "Doesn't match!"; } package main; my $wm = WordMatch->new("hi"); print $wm->match("[hi] how are you?"), "\n"; print $wm->match("hi how are you?"), "\n";
To test it, you might use:package ReadFile; use Symbol; sub new { my $class = shift; $class = ref($class) || $class; my $file = shift; my $self = gensym; open ($self, $file) || die; bless($self, $class); return $self; } sub read_record { my $self = shift; local $/ = shift || $/; my $line = <$self>; return $line; }
The constructor takes the name of the file to open, and the read_record() method takes an alternate input record separator. (Symbol::gensym returns a reference to an anonymous typeglob -- if you were wondering.) It would be good to add a DESTROY method to close the typeglob:my $file = ReadFile->new("obself.pl"); print $file->read_record("package"); print $file->read_record();
sub DESTROY { my $self = shift; close $self; print "Closed!\n"; # just to prove that it's working }
The methods display_args() and display_returns() can search through the comments at the start of the sub, matching however you mark the arguments passed and the return values. Build a hash of an object for each subroutine in your project, and you can iterate through them quickly and easily. This might be part of your test suite.package SubBrowser; sub new { my $class = shift; $class = ref($class) || $class; my $package = shift; my $subname = shift; # assume $package is a reference to a hash of in-memory source cod +e, # keyed by subroutine name my $sub; eval { $sub = $package->{$subname}; }; # ooh, tricky bless($sub, $class); return $sub; } sub display_args { # get data from $package } sub display_returns { # get data from $package } sub test { my $self = shift; return &$self; }
What does this give us over inheritance? Not a whole lot, at first glance. The AUTOLOAD mechanism uses symbolic references and has a performance penalty. (This can be alleviated somewhat by mucking about in the symbol table.)package Wrapper; use vars '$AUTOLOAD'; sub new { my $class = shift; $class = ref($class) || $class; my $obj = shift; my $self = \$obj; bless($self, $class); return $self; } sub AUTOLOAD { my $self = shift; return if $AUTOLOAD =~ /::DESTROY/; $AUTOLOAD =~ s/.*:://; no strict 'refs'; print "Do something interesting here.\n"; return $$self->$AUTOLOAD(@_); } package main; # as before my $wm = WordMatch->new("hi"); print $wm->match("[hi] how are you?"), "\n"; print $wm->match("hi how are you?"), "\n"; # our new version my $wm2 = Wrapper->new(WordMatch->new("Hello")); print $wm2->match("[Hello] little girl"), "\n";
What if the Wrapper class enforced security, though? If the only interface to an otherwise-private-only-by-politeness object were through this Wrapper class, no one would be able to reach inside the object and do bad things. We could hold a reference to the wrapped object in a variable declared in the use vars statement, making it accessible only through the defined Wrapper interface. We could write some an exception handling wrapper around modules known to be buggy or insecure.
You could do lots of things.... You may never need any of these trickeries, but aren't you glad to know they're available?
In reply to Blessables -- What Can You Make Into Objects? by chromatic
For: | Use: | ||
& | & | ||
< | < | ||
> | > | ||
[ | [ | ||
] | ] |