package Template::TT3::Example;
use Template::TT3::Class
version => 3.00, # sets $VERSION number
debug => 0, # sets $DEBUG flag
base => 'Template::Base', # specify base class
utils => 'blessed'; # imports from Template::Utils
# ...and more...
Template::TT3::Class is a class metaprogramming module derived from Badger::Class . You should read the documentation for Badger::Class first to understand the basic principles of what this module does.
The class() subroutine can be used to fetch a Template::TT3::Class object for a package.
package Template::TT3::Example; use Template::TT3::Class 'class';
You can use this object to perform various common class metaprogramming tasks, like setting the version number, using a a debugging flag, defining a base class, and so on.
# set version, base class and debug flag
class->version(3.14);
class->debug(1);
class->base('Template::TT3::Base');
You can also use the import hooks to achieve the same effect.
package Template::TT3::Example;
use Template::TT3::Class
version => 3.14,
debug => 1,
base => 'Template::TT3::Base';
Template::TT3::Class is a subclass of
Badger::Class
and inherits all of
its methods and other features.
In addition the following methods are also defined.
Badger::Class
uses this to determine what to strip off the front of the
class name to generate a short id for a class (e.g. Badger::Example::Foo
without the Badger base_id ends up as example.foo). We're going to
extend that concept to allow individual modules to define a base_id()
method.
NOTE: this may be subject to change
Method to import regular expression patterns from Template::TT3::Patterns . This is typically called as an import hook.
package Template::TT3::Example;
use Template::TT3::Class
patterns => '$INTEGER';
my $text = '123';
if ($text =~ /$INTEGER/) {
print "matched integer: $1\n";
}
Creates an alias to an existing method. The method may be defined in the current class or in a base class.
class->alias( foo => 'bar' ); # foo() is now an alias for bar()
A code reference can also be passed to set a method directly. In this case the method performs the same as method() in Badger::Class .
class->alias(
foo => sub {
...
}
);
This method can be called as an export hook.
package Template::TT3::Example;
use Template::TT3::Class
base => 'Badger::Base',
alias => {
gen_msg => 'message',
};
In the above example, a gen_msg() alias is created in the
Template::TT3::Example module which references the
message()
method defined in the
Badger::Base
base class.
This method can be called to generate other classes.
package Template::TT3::Example;
use Template::TT3::Class
import => 'class';
class->generate(
'Template::TT3::Example::Foo' => {
version => 2.718,
base => 'Template::TT3::Example',
methods => {
wam => sub { ... },
bam => sub { ... },
}
# plus any other Template::TT3::Class import hooks
},
'Template::TT3::Example::Bar' => {
...
}
);
The first argument is a class name. The second argument is a reference to a hash array or list of named parameters. These can include any export hooks defined by Template::TT3::Class or Badger::Class .
This method can be used to create subclasses of the current class.
package Template::TT3::Example;
use Template::TT3::Class
import => 'class';
class->subclass(
'Template::TT3::Example::Foo' => {
version => 2.718,
methods => {
wam => sub { ... },
bam => sub { ... },
}
}
);
As per
generate()
, the first argument is a class name and the second is a
reference to a hash array or list of named parameters giving the class
definition. The current class (Template::TT3::Example in the example above)
will automatically be added as a base class of the new class
(Template::TT3::Example::Foo).
This method can be used to generate a number of operator classes en masse. It should be called from the base class package that you want to subclass operators from.
package Template::TT3::Element::Number;
use Template::TT3::Class 'class';
class->generate_ops(
{
methods => 'value values number text'
},
inc => prefix => sub {
# code implementing 'inc' prefix operator
},
dec => prefix => sub {
# code implementing 'dec' prefix operator
}
);
The first argument is a reference to a hash array containing any configuration options that apply to all the subsequent operators. The remaining arguments specify the operators to be created.
Each operator starts with a short identified (e.g. inc). This is CamelCased
(e.g. to Inc) and appended to the base class name to give a new package
name (e.g. Template::TT3::Element::Number::Inc). Any subsequent
non-reference arguments provide the names of operator base classes for the new
operator. These are CamelCased and appended to the
Template::TT3::Element::Operator base class package (e.g. prefix is
Template::TT3::Element::Operator::Prefix, infix_right is
Template::TT3::Element::Operator::InfixRight, and so on) before being added
as base classes of the new operator. The final argument for an operator as a
code reference which implements an evaluation method for the operator. This
is then installed into the new operator class as the methods listed in the
methods item of the $spec (e.g. value(), values(), number()
and text() in this example).
This method of convenience provides a wrapper around generate_ops() to provide the correct specification (the first argument passed to generate_ops() ) for creating numeric operators.
class->generate_number_ops(
inc => prefix => sub {
# code implementing 'inc' prefix operator
},
dec => prefix => sub {
# code implementing 'dec' prefix operator
}
);
Most numeric operators implement one single evaluation method, value(),
which is then aliased to values(), number() and text().
See Template::TT3::Elements::Number for an example of it in use.
Similar to generate_number_ops() , this method creates new numerical operator classes.
This method of convenience provides a wrapper around generate_ops() to
This method of convenience provides a wrapper around generate_ops() to provide the correct specification for creating text operators.
class->generate_text_ops(
append => infix_left => sub { # a ~ b
# code implementing 'append' infix operator
},
);
Used to generate intermediate classes that are used to switch between two different operators depending on the parse context in which they are used. For example, the minus sign '-' can be used as a prefix operator (negative) or an infix operator (subtraction).
package Template::TT3::Element::Number;
use Template::TT3::Class 'class';
class->generate_pre_post_ops(
minus => ['num_negative', 'num_subtract'],
)
The above code creates a new Template::TT3::Element::Number::Minus class.
When used as a prefix operator (i.e. the parse_expr() method is called on it)
the object will upgrade itself (via reblessing) to a
Template::TT3::Element::Number::Negative object. When used as an infix
operator (or more generally any postfix operator, i.e. when parse_infix() is
called) it will upgrade itself to a
Template::TT3::Element::Number::Subtract object.
See Template::TT3::Elements::Number for an example of it in use.
Andy Wardley http://wardley.org/