Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
Class::Closure(3)     User Contributed Perl Documentation    Class::Closure(3)

NAME
       Class::Closure -	Encapsulated, declarative class	style

VERSION
       version 0.302

SYNOPSIS
	package	Dog;

	use Class::Closure;

	sub CLASS {
	    extends Foo::Bar;		# Inherit from another class

	    extends $some_object;	# Inherit from a single	object (classless)

	    my $hungry;			# private

	    has	my $face;		# read-only

	    public my $leash;		# public

	    accessor 'food',		# magical variable-like	function
		get => sub { 'None' },
		set => sub { $hungry = 0; };

	    method bark	=> sub { print "Woof!" };   # method (note the semicolon)

	    method BUILD => sub	{ print	"A new dog is born" };	# constructor

	    destroy { print "Short is the life of a dog" };  # destructor

	    method FALLBACK => sub { print "Handling $AUTOLOAD"	};
	}

	my $fido = Dog->new;   # "A new	dog is born"
	$fido->face;	       # Get a read-only attribute
	$fido->leash = 'red';  # public	attributes look	like variables
	$fido->food = 20;      # This calls the	food set accessor

DESCRIPTION
       Class::Closure is a package that	makes creating Perl classes less
       cumbersome. You can think of it as a more featureful Class::Struct.

       To declare a class using	Class::Closure,	enter a	new package, use
       Class::Closure, and define a sub	called CLASS. Inside this sub will lie
       the declarations	for the	attributes and methods (and subclasses)	for
       this class.

   Variables
       To declare variables, mark them as lexicals within the sub. You may
       prefix them with	"has" to make them read-only or	"public" to make them
       fully read-write	public.

	sub CLASS {
	    my $x;	       # private
	    has	my $y;	       # read-only
	    public my $z;      # public
	}

       As of the moment, "has" and "public" only support scalar	variables.

       You can give the	variables a default value by assigning to the whole
       declaration. For	simple private variables this is easy; for read-only
       and public variables, it	requires extra parentheses:

	sub CLASS {
	    my $x	  = 1;
	    has(my $y)	  = 2;
	    public(my $z) = 3;
	}

       To use these variables within the class,	use their plain	lexical	name
       with the	sigil. To use them outside the class, call them	as methods.
       Given the class above:

	$obj->x;      #	Illegal; private
	$obj->y;      #	Ok, 2.
	$obj->z;      #	Ok, 3.
	$obj->z	= 32; #	Write to $z.

       This may	be a little different from the usual "$obj->z(32)" syntax you
       might be	used to. Trust me, this	will grow on you.

   Methods
       To declare methods, use the "method" keyword and	pass a name and	a
       reference to a sub:

	sub CLASS {
	    method bark	=> sub {
		print "Woof!\n";
	    };
	}

       The invocant is still passed in as the first argument as	in old-style
       OO. The fact is,	though,	that many times	you won't need it, since you
       can reference the member	variables without it. You still	need it	to
       call functions on yourself, though.

	sub CLASS {
	    method chase_tail => sub {
		my ($self) = @_;
		$self->chase($self->find_tail);
	    };
	}

   Accessors
       Sometimes a change of interface goes from using a public	variable to a
       function	with extra behavior. Some would	say that's why you never make
       a member	variable public. I disagree, since you can just	fake one with
       the "accessor" keyword:

	sub CLASS {
	    accessor 'number',
		    get	{ print	"Getting the number";  42; },
		    set	{ print	"Setting the number";  $_[0]->send($_[1]) };
	}
	print $obj->number;  # "Getting	the number"  "42"
	$obj->number = 314;  # "Setting	the number" ...

   Inheritance
       Unlike the standard Perl	5 object model,	Class::Closure can inherit
       from both classes and variables (like Class::Classless).	Also, it keeps
       their respective	namespaces separate, so	they don't accidentally	stomp
       on each other's member variables, even if they're implemented with the
       standard	object model.

       To inherit, use the "extends" keyword. It can take as an	argument
       either a	class name (make sure you quote	it lest	you confuse Perl) or
       an object. If you need to pass construction parameters to your
       superclass, just	inherit	from it	as an object:

	sub CLASS {
	    extends MySuperClass->new(@params);
	}

   Constructors	and Destructors
       The special method BUILD	is called whenever a new object	is created,
       with the	blessed	object in the first argument and the rest of the
       construction parameters in the remaining	arguments.

       Destructors are a little	different. Because of the magic	that
       Class::Closure has to do	to get them to work with inheritance, they
       have a special syntax:

	sub CLASS {
	    destroy { print "Destructing object"; }
	}

       Yep, that's all.	And you	heard me correctly, they work right with
       inheritance, unlike the standard	"DESTROY" method.

   FALLBACK
       Class::Closure supports an "AUTOLOAD" feature. But because it uses
       "AUTOLOAD" internally, it has to	call it	something else.	It's called
       "FALLBACK", and it works	just like "AUTOLOAD" in	every way (the name of
       the current sub is still	even in	$AUTOLOAD).

   How does it work?
       If you really want to get scary power out of this module, you have to
       understand how it works.

       The "CLASS" sub that you	defined	in your	package	is actually called
       every time an object is created.	That's right, so there's no need for a
       "BUILD" at all (but it makes things look	cleaner). Class::Closure
       exports each one	of these "keywords" into your namespace, and they are
       used right on the spot to construct the object each time.

       Each object's member hash is actually a lexical scratchpad, and it
       keeps track of where it is, so you don't	have to	reference $self	all
       the time. It has	the added plus that each object	in an inheritance
       heirarchy has it's own scratchpad, so you don't get variable name
       conflicts.

       In more detail, when you	call "new" on your package, it derives a new
       anonymous package for only that object. Then when you use "method" (or
       "has" or	"public" or "attribute", which are really just wrappers	around
       the same	thing),	it installs the	sub you	give into that symbol table
       position. These closure's aren't	"cloned", but just referenced, so this
       doesn't take up the horrible amount of memory you might be thinking it
       does.

       Then when all references	to the object disappear, it uses Symbol's
       "delete_package"	to clean out the anonymous package and free memory
       (and more importantly, call "DESTROY"s) associated with the object.

       What does this all mean for you,	the user? Since	you understand that
       these "declarations" are	just sub calls at object construction time,
       you can create your objects based on a dynamic template:

	sub CLASS {
	    my ($class,	$mode) = @_;

	    if ($mode == 1) {
		method foo => sub { ...	};
		method bar => sub { ...	};
	    }
	    else {
		method foo => sub { ...	};
		method bar => sub { ...	};
	    }
	}

       That avoids a run-time check on each of the method calls, and makes
       things a	little easier to read. There's all kinds of other fun stuff
       you can do.

   Technical Notes / Bugs / Caveats / Etc.
       Included	in the distribution is a benchmark.pl script which will	test
       various aspects of Class::Closure objects against objects created with
       the traditional object model. In	general, Class::Closure	is quite a bit
       faster for plain	method calls (the extra	hash lookup for	each attribute
       is more overhead	than you'd think), but is slower for inherited methods
       and much	slower for object creation. So it's not	good to	use
       Class::Closure for small, intermediate objects if you're	worried	about
       speed. Fortunately, Perl	programs tend not to use these sorts of
       objects often.

       "accessor"-like subs with arguments aren't yet supported, but there's
       nothing in the design that says they aren't allowed. I'm	just lazy, and
       I'll happily add	them upon request.

       You might get in	trouble	if you try to define method names the same as
       the exported keyword names.

       There are certainly more	bugs, since this is complex, subtle, scary
       code. Bug reports/patches welcome.

SEE ALSO
       Class::Struct, Class::Classless

AUTHOR
       Aristotle Pagaltzis <pagaltzis@gmx.de>

       Documentation by	Luke Palmer.

COPYRIGHT AND LICENSE
       This documentation is copyright (c) 2004	by Luke	Palmer.

       This software is	copyright (c) 2015 by Aristotle	Pagaltzis.

       This is free software; you can redistribute it and/or modify it under
       the same	terms as the Perl 5 programming	language system	itself.

perl v5.32.1			  2015-01-10		     Class::Closure(3)

NAME | VERSION | SYNOPSIS | DESCRIPTION | SEE ALSO | AUTHOR | COPYRIGHT AND LICENSE

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=Class::Closure&sektion=3&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help