HO::class - class builder for hierarchical objects


   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;


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.


The generated accessor can read and write the data.


The accessor is for read access only.


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;


Development started because there was no class builder for array based objects with all the features I needed.


Yes, there are bugs in this software. Probably it is only good for experiments and not for serious code.


my employer in Leipzig


Sebastian Knapp, <>


Copyright (C) 2007-2017 by Sebastian Knapp

You may distribute this code under the same terms as Perl itself.