NAME
HO::class - class builder for hierarchical objects
SYNOPSIS
package Foo::Bar;
use subs 'init';
use HO::class
_lvalue => hey => '@',
_method => huh => sub { print 'go' },
_rw => bla => '%',
_ro => foo => '$',
_ro => bar => sub { 'dub' },
alias => go => 'huh';
sub init {
my ($self,@args) = @_;
...
return $self;
}
DESCRIPTION
This is a simple class builder for array based objects. Normally it does its job during compile time. A constructor new is build. The generated new will initialize each member with an appropriate default value.
The method init
is reserved for setting up objects during construction. This method gets the fresh build object, and the arguments given calling new
. A little questionable optimization is that the call to init
is not build into the constructor when no such method exists or the option init
is not part of HO::class-\
import> call.
For that reason the pragma subs
is often used, before HO::class
.
Five different keys could be used, to define different accessors.
_rw
-
The generated accessor can read and write the data.
_ro
-
The accessor is for read access only.
_lvalue
_method
_index
alias
-
Currently alias only works for methods and only when the code is given during class definition.
The second field is name of the part from class which will be created. Third field is used for datatype or code references.
Simple Accessors
For this the keys _ro and _rw exists. How the accessor is defined depends on the third argument. The datatypes are defined in HO::accessor class in the global %type
hash.
- @ - data behind the accessor is array reference
- % - a hash reference
- $ - means a scalar and defaults to undef
If the third argument is a subref then the return value of this subref is used as a default value for the attribute. To determine the the type, this code will be called once during construction.
Building a class at runtime
It is possible to build class at runtime. The easiest way to do this, is calling HO::class-\
import>. At runtime the caller is commonly not the wanted class name. For that reason the global variable $HO::accessor::class
is used.
{
local $HO::accessor::class = 'My::Class';
HO::class->import(_ro => acc => '$', init => 'hash');
}
my $obj = My::Class->new(acc => 'data');
Methods Changeable For A Object
You can change methods for an object if you overwrite the method using the index.
package H::first;
use HO::class _method => hw => sub { 'Hallo Welt!' };
my $o2 = H::first->new;
is($o2->hw,'Hallo Welt!'); # ok
$o2->[$o2->_hw] = sub { 'Hello world!' }
is($o2->hw,'Hello world!'); # ok
How you can see, it is quite easy to do this in perl. Here during class construction you have to provide the default method, which is used when the object does not has an own method.
The method name can be appended with an additional parameter static
separated by a colon. This means that the default method is stored in an additional slot in the object. So it is changeable on per class base. This is not the default, because the extra space required.
use HO::XML
_method => namespace:static => sub { undef }
Currently the word behind the colon could be free choosen. Only the existence of a colon in the name is checked.
Add your own types
Your are able to register your own types. The API is low level. Given a simple type like a stack.
package Sample::Stack;
sub new { ... }
sub pop { ... }
sub push { ... }
First the new type needs to be registered. This done by filling the type hasch with the name and a function, which will return an object of that type.
$HO::accessor::type{'stack'} = sub { Sample::Stack->new };
The second step is to implement the accessors. It is implemented by an function, which returns an closure around the given index of the accessor.
$HO::accessor::rw_accessor{'stack'} = sub {
my ($n,$i) = @_;
return sub { my ($obj,$idx,$val) = @_;
return $obj->[$i] if @_ == 1;
}
}
Motivation
Development started because there was no class builder for array based objects with all the features I needed.
BUGS
Yes, there are bugs in this software. Probably it is only good for experiments and not for serious code.
ACKNOWLEDGEMENT
AUTHOR
Sebastian Knapp, <news@young-workers.de>
COPYRIGHT AND LICENSE
Copyright (C) 2007-2017 by Sebastian Knapp
You may distribute this code under the same terms as Perl itself.