The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Class::HPLOO - Easier way to declare classes on Perl, based in the popular class {...} style and ePod.

DESCRIPTION

This is the implemantation of OO-Classes for HPL. This brings an easy way to create PM classes, but with HPL resources/style.

USAGE

  use Class::HPLOO ;

  class Foo extends Bar , Baz {
  
    use LWP::Simple qw(get) ; ## import the method get() to this package.
  
    attr ( array foo_list , int age , string name , foo ) ## define attributes.

    vars ($GLOBAL_VAR) ; ## same as: use vars qw($GLOBAL_VAR);

    my ($local_var) ;
  
    ## constructor/initializer:
    sub Foo {
      $this->{attr} = $_[0] ;
    }
  
    ## methods with input variables declared:
    sub get_pages ($base , \@pages , \%options) {
      my @htmls ;
      
      if ( $options{proxy} ) { ... }
  
      foreach my $pages_i ( @pages ) {
        my $url = "$base/$pages_i" ;
        my $html = get($url) ;
        push(@htmls , $html) ;
        $this->cache($url , $html) ;
      }
      
      return @htmls ;
    }
    
    ## methos like a normal Perl sub:
    sub cache {
      my ( $url , $html ) = @_ ;
      $this->{CACHE}{$url} = $html ;
    }
    
    sub attributes_example {
      $this->set_foo_list(qw(a b c d e f)) ;
      my @l = $this->get_foo_list ;
      
      $this->set_age(30) ;
      $this->set_name("Joe") ;
      $this->set_foo( time() ) ;
      print "NAME: ". $this->get_name ."\n" ;
      print "AGE: ". $this->get_age ."\n" ;
      print "FOO: ". $this->get_foo ."\n" ;
    }
    
  }
  
  ## Example of use of the class:
  
  package main ;
  
  my $foo = new Foo(123) ;
  $foo->get_pages('http://www.perlmonks.com/', ['/index.pl','/foo'] , {proxy => 'localhost:8080'}) ;

CONTRUCTOR

The "method" new() is automatically declared by Class::HPLOO, then it calls the initializer that is a method with the name of the class, like Java.

  class Foo extends {
    ## initializer:
    sub Foo {
      $this->{attr} = $_[0] ;
    }
  }

** Note that what the initializer returns is ignored! Unless you return a new constructed object or UNDEF. Return UNDEF (a constant of the class) makes the creation of the object return undef.

DESTRUCTOR

Use DESTROY() like a normal Perl package.

ATTRIBUTES , GLOBAL VARS & LOCAL VARS

You can use 3 types of definitions for class variables:

ATTRIBUTES

The main difference of an attribute of normal Perl variables, is the existence of the methods set and get for each attribute/key. Also an attribute can have a type definition and a handler, soo each value can be automatically formatted before be really set.

For better OO and persistence of objects ATTRIBUTES should be the main choice.

To set an attribute you use:

To define:

  attr( type name , ref type name , array name , hash name )

To set:

  $this->set_name($val) ;
  ## or:
  $this->{name} = $val ;

To get:

  my $foo = $this->get_name ;
  ## or:
  my $foo = $this->{name} ;

The attr() definition has this syntax:

  REF? ARRAY?|HASH? TYPE? NAME
NAME

The name of the attribute.

An attribute only can be set by set_name() and get by get_name(). It also has a tied key with it's NAME in the HASH reference of the object.

TYPE (optional)

Tells the type of the attribute. If not defined any will be used as default.

Standart types:

any

Accept any type of value.

string | str

A normal string.

integer | int

An integer that accepts only [0-9] digits.

floating | float

A floating point, with the format /\d+\.\d+/. If /\.\d+$/ doesn't exists '.0' will be added in the end.

Personalized types:

To create your own type you can use this syntax:

  attr( &mytypex foo ) ;

Then you need to create the sub that will handle the type format:

  sub mytypex ($value) {
    $value =~ s/x/y/gi ; ## do some formatting.
    return $value ; ## return the value
  }

Note that a type will handle one value/SCALAR per time. Soo, the same type can be used for array attributes or not:

  attr( &mytypex foo , array &mytypex list ) ;

Soo, in the definition above, when list is set with some ARRAY, eache element of the array will be past one by one to the &mytypex sub.

REF (optional)

Tells that the value is a reference. Soo, you need to always set it with a reference:

  attr( ref foo ) ;

  ...
  
  $this->set_foo( \$var ) ;
  ## or
  $this->set_foo( [1 , 2 , 3] ) ;
ARRAY or HASH (optional)

Tells that the value is an array or a hash of some type.

Soo, for this type:

  attr( array int ages ) ;

You can set and get without references:

  $this->set_ages(20 , 25 , 30 , 'invalid' , 40) ;
  
  ...
  
  my @ages = $this->get_ages ;

Note that in this example, all the values of the array will be formated to integer. Soo, the value 'invalid' will be set to undef.

The attribute definition was created to handle object databases and the persistence of objects created with Class::HPLOO. Soo, for object persistence you should use only ATTRIBUTES and GLOBAL VARS.

Note that for object persistence, keys sets in the HASH reference of the object, that aren't defined as attributes, own't be saved. Soo, for the attr() definition below, the key foo won't be persistent:

  attr( str bar , int baz ) ;
  $this->{bar} = 'persistent' ;
  $this->{foo} = 'not persistent' ;

GLOBAL VARS

To set a global variable (static variable of a class), you use this syntax:

  vars ($foo , @bar , %baz) ;

Actually this is the same to write:

  use vars qw($foo @bar %baz) ;

** Note that a global variable is just a normal Perl variable, with a public access in it's package/class.

LOCAL VARS

This are just variables with private access (only accessed by the scope defined with it).

  my ($foo , @bar , %baz) ;

** Note that a local variable is just a normal Perl variable accessed only through it's scope.

METHODS

All the methods of the classes are declared like a normal sub.

You can declare the input variables to receive the arguments of the method:

  sub methodx ($arg1 , $arg2 , \@listref , \%hasref , @rest) {
    ...
  }
  
  ## Calling:
  
  $foo->methodx(123 , 456 , [0,1,2] , {k1 => 'x'} , 7 , 8 , 9 ) ;

HTML BLOCKS

You can use HTML blocks in the class like in HPL documents:

  class Foo {
  
    sub test {
      print <% html_test>(123) ;
    }
    
    <% html_test($n)
      <hr>
      NUMBER: $n
      <hr>    
    %>
  
  }

SUB CLASSES

From version 0.04+ you can declare sub-classes:

  class foo {
    class subfoo { ... }
  }

You also can handle the base name of a class adding "." in the begin of the class name:

  class foo {
    class .in { ... }
  }

In the example above, the class name .in will be translated as foo::in.

DUMP

You can dump the generated code:

  use Class::HPLOO qw(dump nice) ;

** The nice option just try to make a cleaner code.

BUILD

The script "build-hploo.pl" can be used to convert .hploo files to .pm files.

Soo, you can write a Perl Module with Class::HPLOO and release it as a normal .pm file without need Class::HPLOO installed.

If you have ePod (0.03+) installed you can use ePod to write your documentation. For .hploo files the ePod need to be alwasy after __END__.

Note that ePod accepts POD syntax too, soo you still can use normal POD for documentation.

SEE ALSO

Perl6::Classes, HPL.

AUTHOR

Graciliano M. P. <gm@virtuasites.com.br>

I will appreciate any type of feedback (include your opinions and/or suggestions). ;-P

COPYRIGHT

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.