Class::Plain::Document::Cookbook - Cookbook of Class::Plain
Class::Plain::Document::Cookbook
This is the cookbook of the Class::Plain.
Use Class::Plain with existing classes.
Before:
package Point; sub new { my $class = shift; my $self = {@_}; return bless $self, ref $class || $class; } sub x { my $self = shift; if (@_) { $self->{x} = shift; return $self; } return $self->{x}; } sub y { my $self = shift; if (@_) { $self->{y} = shift; return $self; } return $self->{y}; } my $point = Point->new(x => 1, y => 2); $point->x(3); $point->y(4); print $point->x . "\n"; print $point->y . "\n";
After
Use class, field, method keywords.
class
field
method
use Class::Plain; class Point { field x; field y; method new : common { my $self = {@_}; return bless $self, ref $class || $class; } method x { if (@_) { $self->{x} = shift; return $self; } return $self->{x}; } method y { if (@_) { $self->{y} = shift; return $self; } return $self->{y}; } } my $point = Point->new(x => 1, y => 2); $point->x(3); $point->y(4); print $point->x . "\n"; print $point->y . "\n";
If you don't need to take care of the fll backword compatilibity, you can rewrite above code to the following code.
use Class::Plain; class Point { field x : rw; field y : rw; } my $point = Point->new(x => 1, y => 2); $point->x(3); $point->y(4); print $point->x . "\n"; print $point->y . "\n";
A class created by Class::Plain inherits Class::Plain::Base. Class::Plain::Base has the new method.
use Class::Plain; # Inherit Class::Plain::Base class Point { field x; field y; } # (x => 1) my $point = Point->new(x => 1);
This can be customize by overriding the new method.
new
use Class::Plain; class Point { field x; field y; # Override the new method method new : common { my $self = $class->SUPER::new(@_); $self->{x} //= 0; $self->{y} //= 0; return $self; } } # (x => 1, y => 0) my $point = Point->new(x => 1);
An example of the array based object.
use Class::Plain; class ArrayBased { method new : common { return bless [@_], ref $class || $class; } method push { my ($value) = @_; push @$self, $value; } method get { my ($index) = @_; return $self->[$index]; } method to_array { return [@$self]; } } my $object = ArrayBased->new(1, 2); $object->to_array; # [1, 2] $object->push(3); $object->push(5); $object->get(0); # 1 $object->get(1); # 2 $object->get(2); # 3 $object->get(3); # 5 $object->to_array; # [1, 2, 3, 5]
An example of the scalar based object.
use Class::Plain; class ScalarBased { method new : common { my $value = shift; return bless \$value, ref $class || $class; } method to_value { return $$self; } } my $object = ScalarBased->new(3); $object->to_value; # 3;
An example of single inheritance.
use Class::Plain; class Point { field x; field y; method new : common { my $self = $class->SUPER::new(@_); $self->{x} //= 0; $self->{y} //= 0; return $self; } method move { my ($x, $y) = @_; $self->{x} += $x; $self->{y} += $y; } method describe { print "A point at ($self->{x}, $self->{y})\n"; } } my $point = Point->new(x => 5, y => 10); $point->describe; class Point3D : isa(Point) { field z; method new : common { my $self = $class->SUPER::new(@_); $self->{z} //= 0; return $self; } method move { my ($x, $y, $z) = @_; $self->SUPER::move($x, $y); $self->{z} += $z; } method describe { print "A point at ($self->{x}, $self->{y}, $self->{z})\n"; } } my $point3d = Point3D->new(x => 5, y => 10, z => 15); $point3d->describe;
An example of multiple inheritance. It is used for modules using multiple inheritance such as DBIx::Class.
use Class::Plain; # The multiple inheritance class MultiBase1 { field b1 : rw; method ps; method b1_init { push @{$self->ps}, 2; $self->{b1} = 3; } } class MultiBase2 { field b2 : rw; method ps; method b1_init { push @{$self->ps}, 7; $self->{b1} = 8; } method b2_init { push @{$self->ps}, 3; $self->{b2} = 4; } } class MultiClass : isa(MultiBase1) isa(MultiBase2) { field ps : rw; method new : common { my $self = $class->SUPER::new(@_); $self->{ps} //= []; $self->init; return $self; } method init { push @{$self->{ps}}, 1; $self->b1_init; $self->b2_init; } method b1_init { $self->next::method; } method b2_init { $self->next::method; } } my $object = MultiClass->new; $object->b1; # 3 $object->b2; # 4 $object->ps; # [1, 2, 3]
An example of embeding classes. Embeding class is similar to Corinna Role although the methods are embeded manually in the case of using Class::Plain.
use Class::Plain; class EmbedBase1 { field b1 : rw; method ps; method init { push @{$self->ps}, 2; $self->{b1} = 3; } } class EmbedBase2 { field b2 : rw; method ps; method init { push @{$self->ps}, 3; $self->{b2} = 4; } } class EmbedClass { field ps : rw; method new : common { my $self = $class->SUPER::new(@_); $self->{ps} //= []; $self->init; return $self; } method init { push @{$self->{ps}}, 1; $self->EmbedBase1::init; $self->EmbedBase2::init; } method b1 { $self->EmbedBase1::b1(@_) } method b2 { $self->EmbedBase2::b2(@_) } } my $object = EmbedClass->new; $object->b1; # 3 $object->b2; # 4 $object->ps; # [1, 2, 3]
An example of the role. The above example is rewritten by "role" in Class::Plain.
use Class::Plain; role EmbedBase1 { field b1 : rw; method ps; method init { push @{$self->ps}, 2; $self->{b1} = 3; } } role EmbedBase2 { field b2 : rw; method ps; method init { push @{$self->ps}, 3; $self->{b2} = 4; } } class EmbedClass : does(EmbedBase1) does(EmbedBase2) { field ps : rw; method new : common { my $self = $class->SUPER::new(@_); $self->{ps} //= []; $self->init; return $self; } method init { push @{$self->{ps}}, 1; $self->EmbedBase1::init; $self->EmbedBase2::init; } } my $object = EmbedClass->new; print $object->b1 . "\n"; # 3 print $object->b2 . "\n"; # 4 print "@{$object->ps}" . "\n"; # [1, 2, 3]
Class::Plain can be used with other OO modules.
Use Moo with Class::Plain.
use Class::Plain; class Foo : isa() { field x; use Moo; has "x" => (is => 'rw'); method to_string { "String:" . $self->x } } my $object = Foo->new(x => 1); print $object->x . " " . $object->to_string;
Use Class::Accessor::Fast with Class::Plain.
use Class::Plain; class Foo { field x; use base 'Class::Accessor::Fast'; __PACKAGE__->mk_accessors('x'); method to_string { "String:" . $self->x } } my $object = Foo->new(x => 1); print $object->x . " " . $object->to_string;
Use Class::Accessor with Class::Plain.
Use Mojo::Base with Class::Plain.
use Class::Plain; class Foo : isa() { field x; use Mojo::Base -base; has "x"; method to_string { "String:" . $self->x } } my $object = Foo->new(x => 1); print $object->x . " " . $object->to_string;
Weaken a field.
use Scalar::Util 'weaken'; use Class::Plain; class Foo { field x; method weaken_x { weaken $self->{x}; } }
A class variable is represented using a package variable or a lexical variable.
use Class::Plain; class ClassVariable { # Public our $FOO; # Private my $BAR; BEGIN { $FOO = 1; $BAR = 2; } method FOO : common { $FOO } method BAR : common { $BAR } } ClassVariable->FOO: # 1 ClassVariable->BAR; # 2
Use Class::Plain with subroutine signatures from Perl 5.26+.
Perl 5.26+
use v5.36; # Enable signatures and other features. use Class::Plain; class Point { field x; field y; method new : common { my $self = $class->SUPER::new(@_); $self->{x} //= 0; $self->{y} //= 0; return $self; } # Subroutine signatures method move ($x = 0, $y = 0) { $self->{x} += $x; $self->{y} += $y; } method describe { print "A point at ($self->{x}, $self->{y})\n"; } } my $point = Point->new(x => 5, y => 10); $point->describe;
To install Class::Plain, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Class::Plain
CPAN shell
perl -MCPAN -e shell install Class::Plain
For more information on module installation, please visit the detailed CPAN module installation guide.