NAME
Mars::Kind - Kind Base Class
ABSTRACT
Kind Base Class for Perl 5
SYNOPSIS
package User;
use base 'Mars::Kind';
package main;
my $user = User->BLESS(
fname => 'Elliot',
lname => 'Alderson',
);
# bless({fname => 'Elliot', lname => 'Alderson'}, 'User')
# i.e. BLESS is somewhat equivalent to writing
# User->BUILD(bless(User->ARGS(User->BUILDARGS(@args) || User->DATA), 'User'))
DESCRIPTION
This package provides a base class for "class" and "role" (kind) derived packages and provides class building, object construction, and object deconstruction lifecycle hooks. The Mars::Class and Mars::Role packages provide a simple DSL for automating Mars::Kind derived base classes.
METHODS
This package provides the following methods:
args
ARGS(Any @args) (HashRef)
The ARGS method is a object construction lifecycle hook which accepts a list of arguments and returns a blessable data structure.
Since 0.01
- ARGS example 2
-
# given: synopsis package main; my $args = User->ARGS(name => 'Elliot'); # {name => 'Elliot'}
- ARGS example 3
-
# given: synopsis package main; my $args = User->ARGS({name => 'Elliot'}); # {name => 'Elliot'}
attr
ATTR(Str $name, Any @args) (Str | Object)
The ATTR method is a class building lifecycle hook which installs an attribute accessors in the calling package.
Since 0.01
- ATTR example 1
-
package User; use base 'Mars::Kind'; User->ATTR('name'); package main; my $user = User->BLESS; # bless({}, 'User') # $user->name; # "" # $user->name('Elliot'); # "Elliot"
- ATTR example 2
-
package User; use base 'Mars::Kind'; User->ATTR('role'); package main; my $user = User->BLESS(role => 'Engineer'); # bless({role => 'Engineer'}, 'User') # $user->role; # "Engineer" # $user->role('Hacker'); # "Hacker"
audit
AUDIT(Str $role) (Str | Object)
The AUDIT method is a class building lifecycle hook which exist in roles and is executed as a callback when the consuming class invokes the "TEST" hook.
Since 0.01
- AUDIT example 1
-
package HasType; use base 'Mars::Kind'; sub AUDIT { die 'Consumer missing "type" attribute' if !$_[1]->can('type'); } package User; use base 'Mars::Kind'; User->TEST('HasType'); package main; my $user = User->BLESS; # Exception! Consumer missing "type" attribute
- AUDIT example 2
-
package HasType; sub AUDIT { die 'Consumer missing "type" attribute' if !$_[1]->can('type'); } package User; use base 'Mars::Kind'; User->ATTR('type'); User->TEST('HasType'); package main; my $user = User->BLESS; # bless({}, 'User')
base
BASE(Str $name) (Str | Object)
The BASE method is a class building lifecycle hook which registers a base class for the calling package. Note: Unlike the "FROM" hook, this hook doesn't invoke the "AUDIT" hook.
Since 0.01
- BASE example 1
-
package Entity; sub work { return; } package User; use base 'Mars::Kind'; User->BASE('Entity'); package main; my $user = User->BLESS; # bless({}, 'User')
- BASE example 2
-
package Engineer; sub debug { return; } package Entity; sub work { return; } package User; use base 'Mars::Kind'; User->BASE('Entity'); User->BASE('Engineer'); package main; my $user = User->BLESS; # bless({}, 'User')
bless
BLESS(Any @args) (Object)
The BLESS method is an object construction lifecycle hook which returns an instance of the calling package.
Since 0.01
- BLESS example 1
-
package User; use base 'Mars::Kind'; package main; my $example = User->BLESS; # bless({}, 'User')
- BLESS example 2
-
package User; use base 'Mars::Kind'; package main; my $example = User->BLESS(name => 'Elliot'); # bless({name => 'Elliot'}, 'User')
- BLESS example 3
-
package User; use base 'Mars::Kind'; package main; my $example = User->BLESS({name => 'Elliot'}); # bless({name => 'Elliot'}, 'User')
- BLESS example 4
-
package List; use base 'Mars::Kind'; sub ARGS { my ($self, @args) = @_; return @args ? ((@args == 1 && ref $args[0] eq 'ARRAY') ? @args : [@args]) : $self->DATA; } sub DATA { my ($self, $data) = @_; return $data ? [@$data] : []; } package main; my $list = List->BLESS(1..4); # bless([1..4], 'List')
- BLESS example 5
-
package List; use base 'Mars::Kind'; sub ARGS { my ($self, @args) = @_; return @args ? ((@args == 1 && ref $args[0] eq 'ARRAY') ? @args : [@args]) : $self->DATA; } sub DATA { my ($self, $data) = @_; return $data ? [@$data] : []; } package main; my $list = List->BLESS([1..4]); # bless([1..4], 'List')
build
BUILD(HashRef $data) (Object)
The BUILD method is an object construction lifecycle hook which receives an object and the data structure that was blessed, and should return an object although its return value is ignored by the "BLESS" hook.
Since 0.01
- BUILD example 1
-
package User; use base 'Mars::Kind'; sub BUILD { my ($self) = @_; $self->{name} = 'Mr. Robot'; return $self; } package main; my $example = User->BLESS(name => 'Elliot'); # bless({name => 'Mr. Robot'}, 'User')
- BUILD example 2
-
package User; use base 'Mars::Kind'; sub BUILD { my ($self) = @_; $self->{name} = 'Mr. Robot'; return $self; } package Elliot; use base 'User'; sub BUILD { my ($self, $data) = @_; $self->SUPER::BUILD($data); $self->{name} = 'Elliot'; return $self; } package main; my $elliot = Elliot->BLESS; # bless({name => 'Elliot'}, 'Elliot')
buildargs
BUILDARGS(Any @args) (Any @args | HashRef $data)
The BUILDARGS method is an object construction lifecycle hook which receives the arguments provided to the constructor (unaltered) and should return a list of arguments, a hashref, or key/value pairs.
Since 0.01
- BUILDARGS example 1
-
package User; use base 'Mars::Kind'; sub BUILD { my ($self) = @_; return $self; } sub BUILDARGS { my ($self, @args) = @_; my $data = @args == 1 && !ref $args[0] ? {name => $args[0]} : {}; return $data; } package main; my $user = User->BLESS('Elliot'); # bless({name => 'Elliot'}, 'User')
data
DATA() (Ref)
The DATA method is an object construction lifecycle hook which returns the default data structure reference to be blessed when no arguments are provided to the constructor. The default data structure is an empty hashref.
Since 0.01
- DATA example 1
-
package Example; use base 'Mars::Kind'; sub DATA { return []; } package main; my $example = Example->BLESS; # bless([], 'Example')
- DATA example 2
-
package Example; use base 'Mars::Kind'; sub DATA { return {}; } package main; my $example = Example->BLESS; # bless({}, 'Example')
destroy
DESTROY() (Any)
The DESTROY method is an object destruction lifecycle hook which is called when the last reference to the object goes away.
Since 0.01
- DESTROY example 1
-
package User; use base 'Mars::Kind'; our $USERS = 0; sub BUILD { return $USERS++; } sub DESTROY { return $USERS--; } package main; my $user = User->BLESS(name => 'Elliot'); undef $user; # 1
does
DOES(Str $name) (Bool)
The DOES method returns true or false if the invocant consumed the role or interface provided.
Since 0.01
- DOES example 1
-
package Admin; use base 'Mars::Kind'; package User; use base 'Mars::Kind'; User->ROLE('Admin'); sub BUILD { return; } sub BUILDARGS { return; } package main; my $admin = User->DOES('Admin'); # 1
- DOES example 2
-
package Admin; use base 'Mars::Kind'; package User; use base 'Mars::Kind'; User->ROLE('Admin'); sub BUILD { return; } sub BUILDARGS { return; } package main; my $is_owner = User->DOES('Owner'); # 0
export
EXPORT(Any @args) (ArrayRef)
The EXPORT method is a class building lifecycle hook which returns an arrayref of routine names to be automatically imported by the calling package whenever the "ROLE" or "TEST" hooks are used.
Since 0.01
- EXPORT example 1
-
package Admin; use base 'Mars::Kind'; sub shutdown { return; } sub EXPORT { ['shutdown'] } package User; use base 'Mars::Kind'; User->ROLE('Admin'); package main; my $user = User->BLESS; # bless({}, 'User')
from
FROM(Str $name) (Str | Object)
The FROM method is a class building lifecycle hook which registers a base class for the calling package, automatically invoking the "AUDIT" hook on the base class.
Since 0.03
- FROM example 1
-
package Entity; use base 'Mars::Kind'; sub AUDIT { my ($self, $from) = @_; die "Missing startup" if !$from->can('startup'); die "Missing shutdown" if !$from->can('shutdown'); } package User; use base 'Mars::Kind'; User->ATTR('startup'); User->ATTR('shutdown'); User->FROM('Entity'); package main; my $user = User->BLESS; # bless({}, 'User')
- FROM example 2
-
package Entity; use base 'Mars::Kind'; sub AUDIT { my ($self, $from) = @_; die "Missing startup" if !$from->can('startup'); die "Missing shutdown" if !$from->can('shutdown'); } package User; use base 'Mars::Kind'; User->FROM('Entity'); sub startup { return; } sub shutdown { return; } package main; my $user = User->BLESS; # bless({}, 'User')
import
IMPORT(Str $into, Any @args) (Str | Object)
The IMPORT method is a class building lifecycle hook which dispatches the "EXPORT" lifecycle hook whenever the "ROLE" or "TEST" hooks are used.
Since 0.01
- IMPORT example 1
-
package Admin; use base 'Mars::Kind'; our $USES = 0; sub shutdown { return; } sub EXPORT { ['shutdown'] } sub IMPORT { my ($self, $into) = @_; $self->SUPER::IMPORT($into); $USES++; return $self; } package User; use base 'Mars::Kind'; User->ROLE('Admin'); package main; my $user = User->BLESS; # bless({}, 'User')
meta
META() (Meta)
The META method return a Mars::Meta object which describes the invocant's configuration.
Since 0.01
- META example 1
-
package User; use base 'Mars::Kind'; package main; my $meta = User->META; # bless({name => 'User'}, 'Mars::Meta')
name
NAME() (Str)
The NAME method is a class building lifecycle hook which returns the name of the package.
Since 0.01
- NAME example 2
-
package User; use base 'Mars::Kind'; package main; my $name = User->BLESS->NAME; # "User"
role
ROLE(Str $name) (Str | Object)
The ROLE method is a class building lifecycle hook which consumes the role provided, automatically invoking the role's "IMPORT" hook. Note: Unlike the "TEST" and "WITH" hooks, this hook doesn't invoke the "AUDIT" hook. The role composition semantics are as follows: Routines to be consumed must be explicitly declared via the "EXPORT" hook. Routines will be copied to the consumer unless they already exist (excluding routines from base classes, which will be overridden). If multiple roles are consumed having routines with the same name (i.e. naming collisions) the first routine copied wins.
Since 0.01
- ROLE example 1
-
package Admin; use base 'Mars::Kind'; package User; use base 'Mars::Kind'; User->ROLE('Admin'); package main; my $admin = User->DOES('Admin'); # 1
- ROLE example 2
-
package Create; use base 'Mars::Kind'; package Delete; use base 'Mars::Kind'; package Manage; use base 'Mars::Kind'; Manage->ROLE('Create'); Manage->ROLE('Delete'); package User; use base 'Mars::Kind'; User->ROLE('Manage'); package main; my $create = User->DOES('Create'); # 1
subs
SUBS() (ArrayRef)
The SUBS method returns the routines defined on the package and consumed from roles, but not inherited by superclasses.
Since 0.01
- SUBS example 1
-
package Example; use base 'Mars::Kind'; package main; my $subs = Example->SUBS; # [...]
test
TEST(Str $name) (Str | Object)
The TEST method is a class building lifecycle hook which consumes the role provided, automatically invoking the role's "IMPORT" hook as well as the "AUDIT" hook if defined.
Since 0.01
- TEST example 1
-
package Admin; use base 'Mars::Kind'; sub AUDIT { my ($self, $from) = @_; die "Missing startup" if !$from->can('startup'); die "Missing shutdown" if !$from->can('shutdown'); } sub AUDIT_BUILD { my ($self, $data) = @_; die "Attribute 'startup' can't be undefined" if !$self->startup; die "Attribute 'shutdown' can't be undefined" if !$self->shutdown; } package User; use base 'Mars::Kind'; User->ATTR('startup'); User->ATTR('shutdown'); User->TEST('Admin'); sub BUILD { my ($self, $data) = @_; # Using AUDIT_BUILD as a callback $self->Admin::AUDIT_BUILD($data); } package main; my $user = User->BLESS(startup => 'hello'); # Exception! Attribute 'shutdown' can't be undefined
AUTHORS
Awncorp, awncorp@cpan.org