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/