NAME
OP::Class - Root-level "Class" class
VERSION
$Id: //depotit/tools/source/snitchd-0.20/lib/OP/Class.pm#9 $
SYNOPSIS
Class Allocation
#
# File: OP/Example.pm
#
use OP qw| create true false |;
create "OP::Example" => {
#
# This is an empty class prototype
#
};
Class Consumer
#
# File: testscript.pl
#
use strict;
use warnings;
use OP::Example;
my $exa = OP::Example->new();
$exa->setName("My First OP Object");
$exa->save("This is a checkin comment");
say "Saved object:";
$exa->print();
DESCRIPTION
OP::Class is the root-level parent class in OP, and also provides the class prototyping function create()
.
METHODS
Public Class Methods
get(OP::Class $class: Str $key)
Get the named class variable
my $class = "OP::Example"; my $scalar = $class->get($key); my @array = $class->get($key); my %hash = $class->get($key);
set(OP::Class $class: Str $key, *@value)
Set the named class variable to the received value
my $class = "OP::Example"; $class->set($key, $scalar); $class->set($key, @array); $class->set($key, %hash);
pretty(OP::Class $class: Str $key)
Transform camelCase to Not Camel Case
my $class = "OP::Example"; my $uglyStr = "betterGetThatLookedAt"; my $prettyStr = $class->pretty($uglyStr);
members(OP::Class $class:)
Class introspection method.
Return an array ref of all messages supported by this class.
Does not include messages from superclasses.
my $members = OP::Example->members();
membersHash(OP::Class $class:)
Class introspection method.
Return a hash ref of all messages supported by this class.
Does not include messages from superclasses.
my $membersHash = OP::Example->membersHash();
Private Class Methods
init(OP::Class $class:)
Abstract callback method invoked immediately after a new class is allocated via create().
Override in subclass with additional logic, if necessary.
__checkVarName(OP::Class $class: Str $varName)
Checks the "safeness" of a class variable name before eval'ing it.
PROTOTYPE COMPONENTS
Class (Package) Name
The name of the class being created is the first argument sent to create()
.
use OP qw| create |;
#
# The class name will be "OP::Example":
#
create "OP::Example" => {
};
Class Prototype
A class prototype is a hash describing all fundamental characteristics of an object class. It's the second argument sent to create()
.
create "OP::Example" => {
#
# This is an empty prototype (perfectly valid)
#
};
Instance Variables
Instance variables are declared with the assert
class method:
create "YourApp::Example" => {
favoriteNumber => OP::Int->assert(
::optional
),
favoriteColor => OP::Str->assert(
qw| red green blue |,
::optional
),
};
Instance Methods
Instance methods are declared as keys in the class prototype. The name of the method is the key, and its value in the prototype is a Perl 5 sub{}
.
create "OP::Example" => {
#
# Add a public instance method, $self->handleFoo()
#
handleFoo => sub {
my $self = shift;
printf 'The value of foo is %s', $self->foo();
print "\n";
return true;
}
}
my $exa = OP::Example->new();
$exa->setFoo("Bar");
$exa->handleFoo();
#
# Expected output:
#
# The value of foo is Bar
#
The OP convention for private or protected instance methods is to prefix them with a single underscore.
create "OP::Example" => {
#
# private instance method
#
_handleFoo => sub {
my $self = shift;
say "The value of foo is $self->{foo}";
}
};
Class Variables
Class variables are declared as keys in the class prototype. They should be prepended with double underscores (__). The value in the prototype is the literal value to be used for the class variable.
use OP qw| create true false |;
create "OP::Example" => {
#
# Override a few class variables
#
__useYaml => false,
__dbiType => OP::DBIType::MySQL
};
OP class variables are just Perl package variables, scoped in a list using our
.
package OP::Example;
use OP qw| true false |;
use base qw| OP::Node |;
our @__useYaml = false;
our @__dbiType = OP::DBIType::MySQL;
true;
Class Methods
Class methods are declared in the same manner as instance methods. The only difference is that the class will be the receiver.
create "OP::Example" => {
#
# Add a public class method
#
loadXml => sub {
my $class = shift;
my $xml = shift;
# ...
}
};
The OP convention for private or protected class methods is to prefix them with double underscores.
create "OP::Example" => {
#
# Override a private class method
#
__basePath => sub {
my $class = shift;
return join('/', '/tmp', $class);
}
};
Inheritance
By default, classes created with create()
inherit from OP::Node. To override this, include a __BASE__
attribute, specifying the parent class name.
create "OP::Example" => {
#
# Override parent class
#
__BASE__ => "Acme::CustomClass"
};
OPTIONAL EXPORTS
Constants
true
,false
Constants provided by OP::Enum::Bool
use OP qw| true false |;
Functions
create(Str $class: Hash $prototype)
use OP qw| create |;
Allocate a new OP-derived class.
Objects instantiated from classes allocated with
create()
have built-in runtime assertions-- simple but powerful rules in the class prototype which define runtime and schema attributes. See the OP::Type module for more about assertions.OP classes are regular old Perl packages.
create()
is just a wrapper to thepackage
keyword, with some shortcuts thrown in.use OP qw| create true false |; create "OP::Example" => { __someClassVar => true, someInstanceVar => OP::Str->assert(), anotherInstanceVar => OP::Str->assert(), publicInstanceMethod => sub { my $self = shift; # ... }, _privateInstanceMethod => sub { my $self = shift; # ... }, publicClassMethod => sub { my $class = shift; # ... }, __privateClassMethod => sub { my $class = shift; # ... }, };
DIAGNOSTICS
XXX TODO Figure out what to put in this section.
CONFIGURATION AND ENVIRONMENT
OP looks for the .oprc
configuration file under the location specified by $OP_HOME
. See OP::Constants for details.
OP under mod_perl/mod_perl2
OP classes should be precompiled under mod_perl by referencing them in the Apache instance's startup.pl
script. OP_HOME must be set in a BEGIN block.
#
# File: startup.pl
#
BEGIN {
$ENV{OP_HOME} = '/home/user/op'; # Directory with the .oprc
}
#
# Load any OP-derived packages at startup:
#
use MyApp::Component;
use MyApp::OtherComponent;
1;
OP under HTML::Mason
OP classes should be preloaded by startup.pl
, as in the above example.
If (and only if) you are not using a startup.pl: Mason loads packages outside the context of package main
, but OP must currently be bootstrapped from package main
, so one must explicitly drop back into main
before consuming OP-derived classes. Do this in a do
block.
<%init>
do {
package main;
use MyApp::Component;
}
</%init>
<%perl>
$m->print( MyApp::Component->sayHello() );
</%perl>
It is highly recommended that startup.pl be used in production environments, so the initial requests to the webserver are not delayed by the lengthy source filtering and compilation steps.
#
# File: httpd.conf
#
PerlModule HTML::Mason::ApacheHandler
PerlRequire /opt/op/bin/startup.pl
<LocationMatch "/.*\.html$">
SetHandler perl-script
PerlHandler HTML::Mason::ApacheHandler
</LocationMatch>
DEPENDENCIES
OP's dependencies are numerous, and subject to change while the API is ironed out. See the Makefile.PL which accompanied this distribution for a current list of prerequisites.
INCOMPATIBILITIES
Probably.
BUGS AND LIMITATIONS
Likely.
Test suite is currently incomplete.
SEE ALSO
This file is part of OP.