Javascript style pseudo-classes in Perl
I am as much a Javascript developer as a Perl developer, and that is primarily because of the striking similarities the languages share, one of the most useful of which is the concept of closures.
Having private(hidden) data, and public accessors/mutators has always been one of the key reasons people use the object oriented paradigm. Perl however, being the flexible language that it is, does not provide any direct way to hide the data in your objects. One of the solutions to this problem is inside-out objects (and I think it is a very elegant solution too.)
But, when I want to write lesser code, and don't really want to use all of Perl's OO functionality, I simply use closures.
Here's how,
#!/usr/bin/perl
use strict;
use warnings;
sub Person{
my $data={
_NAME=>$_[0] || "Anon",
_AGE=>$_[1] || 0,
_PHONE=>$_[2] || "001"
};
# Now the following is an anonymous hash of anonymous methods.
# It contains all the methods to access the above data hash.
my $methods={
name=>sub{
$data->{_NAME}=shift if @_;
$data->{_NAME};
},
age=>sub{
$data->{_AGE}=shift if @_;
$data->{_AGE};
},
phone=>sub{
$data->{_PHONE}=shift if @_;
$data->{_PHONE};
},
say_hello=>sub{
print "Hello ".$data->{_NAME},"\n";
}
};
# Now I make sure only the methods are available outside
return $methods;
}
#Here is a sample of simple inheritance
sub Employee{
my $methods=Person(@_);
my $data={
_COMPANY=>$_[3] || "Unemployed" #You can't use shift here
};
$methods->{company}=sub {
$data->{_COMPANY}=shift if @_;
$data->{_COMPANY};
};
#Now Employee pseudo-class has the extra company() accessor/mutator
return $methods;
}
#Now I create the pseudo-objects
my $person=Person("Hathy",26,"+919919");
$person->{say_hello}();
$person->{name}("Hathibelagal");
$person->{age}($person->{age}()+1);
print $person->{name}()," is ",$person->{age}()," years old\n";
#This is another pseudo-object (With inheritance)
my $employee=Employee("Bela",25,"+01119","Mozilla");
$employee->{say_hello}();
print $employee->{name}()," works for ",$employee->{company}();
#Works just the way it should
Yeah, I understand it is not a class, but you do get some class-like functionality with this style of coding, and very often the purpose of having a class is served.
Very interesting, thanx.
It may be helpfully for some simple things.
As for me, I usually use my own Object::Botox, its like Acessor::Fast, but I wrote its by myself :).
Very nice. Thanks for the post. I've just finishing a project which would have benefited from this. I have a pet project that WILL benefit from it. Very nice indeed.