This module attempts to give Perl a more formal OO implementation framework. Providing a distinction between class properties and methods with three levels of access (Public, Protected and Private). It also restricts method overriding in children classes to those properties or methods marked as "Virtual", in which case a child class can override the method but only from its own context. As far as the parent is concern the overridden method or property still behaves in the expected way from its perspective.

Take the example above:

Any children of MyClass can override the method "OpinionAboutPerl6" as it is marked "Virtual":

However if the public method "RealPublicOpinionAboutPerl6" it's called then it would in turn call the "OpinionAboutPerl6" method as it was defined in MyClass, because from the parents perspective the method never changed. I believe this is crucial behavior and it goes along with how the OO principles have been implemented in other popular languages like Java, C# and C++.

Let's say that we have a hash '%args' which contains parameters from a form submission and you only want to set those properties that belong to group 'FormStep1' and disregards all other args.

@$obj{ $obj->pGroup('FormStep1') } = @args{ $obj->pGroup('FormStep1') };
# now we check for data validation errors
if ($obj->pErrors)
{
warn "We have the following errors: ",Dumper($obj->pGetErrors),"\n";
# now do something with your errors like rendering the form again and
# showing the user the errors.
}

Class properties are defined by use of the "Property" function attribute. Properties like methods have three levels of access (see. Access Levels) which are Public, Protected and Private. In addition to the various access levels properties can be marked as Virtual, which allows them to be overridden in sub-clases and gives them visibility through the entire class hierarchy.

The "Property" keyword is used as a function attribute to declare a class property. Property and Method are mutually exclusive and should never be used on the same function.

Sample usage:

The minimum requirement of a property is be declared with the Property function attribute and for it to return a valid hash ref describing at least its basic type. More about types in the type sub-section.

sub FirstName : Property
{
{
'type' => 'string'
}
}

Here we combine the Property attribute with the Public access modified. Note that order does not matter when combining POOF function attributes.

Properties are declared by the Property function attribute and defined by their definition hash. The definition has allows for various definitions such as type, default value, min value, etc. See the section below for a list of possible definitions.

As the name implies defines the type of the property. POOF has several built in basic types, additionally you can set type to be the namespace (package name) of the object you intend to store in the property.

The qr operator allows the regex to be pre-compiled and you can specify additional switches like in the case above i for non-case sensitive. Data validation failure of regex will result in error code 121.

ifilter is a callback hook in the form of code ref that executes when a property is assigned a value and before we attempt to validate the data. The code ref can be an anonymous subroutine defined in-line or a a ref to a named sub-routine. The filter gets a reference to the object in which they exists along with the value that is being set. The value can be manipulated within the filter and/or validated by calling die if one desires to reject the value before it's set.

Note that because you have a reference to the object you also have access to other properties from the filter to both set and get, however you must be careful to no create an infinite loop by setting or getting values to a property that calls the same filter.

Obviously the example above assumes with have a method "ContainsPropfanity" that will check the contents of $val and returns true if profanity is detected. See the section on Errors and Exceptions handling for more information on data validation violation and handling of die within filters.

Methods are declared using the Method function attribute. Subroutines marked with the Method attribute will be deleted from the symbol table right after compilation and their access will be controlled by the framework. All three access modifiers (Public, Protected and Private) work with methods as well as the Virtual modifier. See Access Modifiers for more information.

Methods and Properties marked as Public can be access by the defining class, its children and the outside world. This is very much how standard Perl subroutines work, therefore using the function attribute Public is merely a formalization. Method and Properties not marked with any access modifiers will default to Public

Methods and Properties marked as Private will be accessible only by the defining class. In fact, you can define a Private method in one class, inherit from that class and define another Private method in the child class and not have a conflict. Each class will use its version of the method. Very useful when you want to control what gets inherited.

By default POOF will not allow you override methods or properties in child classes, only those methods or properties declared as Virtual can be overriden, the only exception is Private methods or properties that are not inheritable thus really private, but will alway be accesible by its definer class.

POOF provides a series utility methods and functions listed below, all but new (the constructor) and _init the instance initialization function are prefixed with a "p" in order not to pollute your namespace too much. This allows you to have your own "Errors" method as the POOF one is called "pErrors" and so son...

Note: Currently some of these methods also exist in POOF without the "p" and I'm working to removed then in a timely manner.

The standard Perl constructor, a bit of processing is done in the constructor so you should not override it. If you need to do things in the constructor override the _init method instead. You've been warned :)

This is a safe place where you can do things right after the object has been instantiated. Things normally done here include processing constructor arguments, setting of default values, etc..

sub _init
{
my $obj = shift;
# make sure we call super so it does its thing
my %args = $obj->SUPER::_init(@_);
# do something here ...
# make sure we return %args to if some inherits from us
# and they call super to get their args they get what its expected.
return %args;
}

Returns and integer representing the number of errors or exceptions currently in the exception tree. Whenever data validation on a property fails an exception or error is stored for the instance in question and the number of such errors can be retrieved by calling this method.

Like pGetErrors above this method returns errors with their property name, code and description but it does so recursively across any contained objects.

For example:

class Car contains class engine stored in the Engine property.

file: Car.pm

package Car;
use strict;
use base qw(POOF);
use Engine;
sub _init
{
my $obj = shift;
# make sure we call super so it does its thing
my %args = $obj->SUPER::_init(@_);
$obj->{'Engine'} = Engine->new;
$obj->{'Engine'}->{'State'} = 'stoped';
# make sure we return %args to if some inherits from us
# and they call super to get their args they get what its expected.
return %args;
}
sub Engine : Property Public
{
{
'type' => 'Engine'
}
}
1;

Note: property names are encoded with a dash to depict the containment level. In the example above "Engine-State" is "Engine" the name of the property containing the object and "State" the name of the property containing the error condition.

Returns a hash indexed by the property names and containing the properties values. Everything is always returned in the order it was defined. Even though the core of the POOF object behaves like a hash the order is always maintained.

on a class with properties that belong to a group called 'SomeGroup' and this group has members 'prop1', 'prop2' and 'prop3';

Takes in a reference to a POOF object, a value and a list of levels normally property names. It will use traverse the object model recursively and set the leaf node to the value.

For example:

$obj->pSetPropertyDeeply($refObj,'stopped','Engine','State');

same as

$refObj->{'Engine'}->{'State'} = 'stopped';

This method along with its counterpart below are useful for traversing complex object structures without having to use eval when generating code automatically and when using introspection. The Encoder class uses them to take "-" encoded properties from form fields to populate your application. There are three other POOF modules that I will publish very soon "POOF-Application-Simple", "POOF-HTML-Form" and "POOF-Webservices" that make use of these facilities.

Although this framework is currently being used in production environments, I cannot accept responsibility for any damages cause by this framework, use only at your own risk.

Documentation for this module is a work in progress. I hope to be able to dedicate more time and created a more comprehensive set of docs in the near future. Anyone interested in helping with the documentation, please contact me at bmillares@cpan.org.

I'd would like to take this opportunity to thank my friends, Buddy Burden, Alain Avakian, John Callender, Diane Xu, Matthew Silvera and Dave Trischuk for their support and valuable input which has help shape the direction of this module.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.