Class::Std man page on Pidora

Man page or keyword search:  
man Server   31170 pages
apropos Keyword Search (all sections)
Output format
Pidora logo
[printable version]

Class::Std(3)	      User Contributed Perl Documentation	 Class::Std(3)

NAME
       Class::Std - Support for creating standard "inside-out" classes

VERSION
       This document describes Class::Std version 0.0.8

SYNOPSIS
	   package MyClass;
	   use Class::Std;

	   # Create storage for object attributes...
	   my %name : ATTR;
	   my %rank : ATTR;
	   my %snum : ATTR;

	   my %public_data : ATTR;

	   # Handle initialization of objects of this class...
	   sub BUILD {
	       my ($self, $obj_ID, $arg_ref) = @_;

	       $name{$obj_ID} = check_name( $arg_ref->{name} );
	       $rank{$obj_ID} = check_rank( $arg_ref->{rank} );
	       $snum{$obj_ID} = _gen_uniq_serial_num();
	   }

	   # Handle cleanup of objects of this class...
	   sub DEMOLISH {
	       my ($self, $obj_ID) = @_;

	       _recycle_serial_num( $snum{$obj_ID} );
	   }

	   # Handle unknown method calls...
	   sub AUTOMETHOD {
	       my ($self, $obj_ID, @other_args) = @_;

	       # Return any public data...
	       if ( m/\A get_(.*)/ ) {	# Method name passed in $_
		   my $get_what = $1;
		   return sub {
		       return $public_data{$obj_ID}{$get_what};
		   }
	       }

	       warn "Can't call $method_name on ", ref $self, " object";

	       return;	 # The call is declined by not returning a sub ref
	   }

DESCRIPTION
       This module provides tools that help to implement the "inside out
       object" class structure in a convenient and standard way.

       Portions of the following code and documentation from "Perl Best
       Practices" copyright (c) 2005 by O'Reilly Media, Inc. and reprinted
       with permission.

   Introduction
       Most programmers who use Perl's object-oriented features construct
       their objects by blessing a hash. But, in doing so, they undermine the
       robustness of the OO approach. Hash-based objects are unencapsulated:
       their entries are open for the world to access and modify.

       Objects without effective encapsulation are vulnerable. Instead of
       politely respecting their public interface, some clever client coder
       inevitably will realize that it's marginally faster to interact
       directly with the underlying implementation, pulling out attribute
       values directly from the hash of an object:

	   for my $file ( get_file_objs() ) {
	       print $file->{name}, "\n";
	   }

       instead of using the official interface:

	   for my $file ( get_file_objs() ) {
	       print $file->get_name(), "\n";
	   }

       From the moment someone does that, your class is no longer cleanly
       decoupled from the code that uses it. You can't be sure that any bugs
       in your class are actually caused by the internals of your class, and
       not the result of some kind of monkeying by the client code. And to
       make matters worse, now you can't ever change those internals without
       the risk of breaking some other part of the system.

       There is a simple, convenient, and utterly secure way to prevent client
       code from accessing the internals of the objects you provide. Happily,
       that approach also guards against misspelling attribute names (a common
       error in hash-based classes), as well as being just as fast as--and
       often more memory-efficient than--ordinary hash-based objects.

       That approach is referred to by various names--flyweight scalars,
       warehoused attributes, inverted indices--but most commonly it's known
       as: inside-out objects. Consider the following class definitions:

	   package File::Hierarchy;
	   {
	       # Objects of this class have the following attributes...
	       my %root_of;   # The root directory of the file hierarchy
	       my %files_of;  # Array storing object for each file in root directory

	       # Constructor takes path of file system root directory...
	       sub new {
		   my ($class, $root) = @_;

		   # Bless a scalar to instantiate the new object...
		   my $new_object = bless \do{my $anon_scalar}, $class;

		   # Initialize the object's "root" attribute...
		   $root_of{ident $new_object} = $root;

		   return $new_object;
	       }

	       # Retrieve files from root directory...
	       sub get_files {
		   my ($self) = @_;

		   # Load up the "files" attribute, if necessary...
		   if (!exists $files_of{ident $self}) {
		       $files_of{ident $self}
			   = File::System->list_files($root_of{ident $self});
		   }

		   # Flatten the "files" attribute's array to produce a file list...
		   return @{ $files_of{ident $self} };
	       }
	   }

	   package File::Hierarchy::File;
	   {
	       # Objects of this class have the following attributes...
	       my %name_of;  # the name of the file

	       # Constructor takes name of file...
	       sub new {
		   my ($class, $filename) = @_;

		   # Bless a scalar to instantiate the new object...
		   my $new_object = bless \do{my $anon_scalar}, $class;

		   # Initialize the object's "name" attribute...
		   $name_of{ident $new_object} = $filename;

		   return $new_object;
	       }

	       # Retrieve name of file...
	       sub get_name {
		   my ($self) = @_;

		   return $name_of{ident $self};
	       }
	   }

       Unlike a hash-based class, each of these inside-out class is specified
       inside a surrounding code block:

	   package File::Hierarchy;
	   {
	       # [Class specification here]
	   }

	   package File::Hierarchy::File;
	   {
	       # [Class specification here]
	   }

       That block is vital, because it creates a limited scope, to which any
       lexical variables that are declared as part of the class will
       automatically be restricted.

       The next difference between the two versions of the classes is that
       each attribute of all the objects in the class is now stored in a
       separate single hash:

	   # Objects of this class have the following attributes...

	   my %root_of;	  # The root directory of the file hierarchy
	   my %files_of;  # Array storing object for each file in root directory

       This is 90 degrees to the usual hash-based approach. In hash-based
       classes, all the attributes of one object are stored in a single hash;
       in inside-out classes, one attribute from all objects is stored in a
       single hash. Diagrammatically:

	   Hash-based:
			    Attribute 1	     Attribute 2

	    Object A	{ attr1 => $valA1,  attr2 => $val2 }

	    Object B	{ attr1 => $valB1,  attr2 => $val2 }

	    Object C	{ attr1 => $valB1,  attr2 => $val2 }

	   Inside-out:
			     Object A		Object B	  Object C

	   Attribute 1	{ 19817 => $valA1,  172616 => $valB1,  67142 => $valC1 }

	   Attribute 2	{ 19817 => $valA2,  172616 => $valB2,  67142 => $valC3 }

	   Attribute 3	{ 19817 => $valA3,  172616 => $valB3,  67142 => $valC3 }

       So the attributes belonging to each object are distributed across a set
       of predeclared hashes, rather than being squashed together into one
       anonymous hash.

       This is a significant improvement. By telling Perl what attributes you
       expect to use, you enable the compiler to check--via use strict--that
       you do indeed use only those attributes.

       That's because of the third difference in the two approaches. Each
       attribute of a hash-based object is stored in an entry in the object's
       hash: "$self->{name}". In other words, the name of a hash-based
       attribute is symbolic: specified by the string value of a hash key. In
       contrast, each attribute of an inside-out object is stored in an entry
       of the attribute's hash: $name_of{ident $self}. So the name of an
       inside-out attribute isn't symbolic; it's a hard-coded variable name.

       With hash-based objects, if an attribute name is accidentally
       misspelled in some method:

	   sub set_name {
	       my ($self, $new_name) = @_;

	       $self->{naem} = $new_name;	      # Oops!

	       return;
	   }

       then the $self hash will obligingly--and silently!--create a new entry
       in the hash, with the key 'naem', then assign the new name to it. But
       since every other method in the class correctly refers to the attribute
       as "$self-"{name}>, assigning the new value to "$self-"{naem}>
       effectively makes that assigned value "vanish".

       With inside-out objects, however, an object's "name" attribute is
       stored as an entry in the class's lexical %name_of hash. If the
       attribute name is misspelled then you're attempting to refer to an
       entirely different hash: %naem_of. Like so:

	   sub set_name {
	       my ($self, $new_name) = @_;

	       $naem_of{ident $self} = $new_name;     # Kaboom!

	       return;
	   }

       But, since there's no such hash declared in the scope, use strict will
       complain (with extreme prejudice):

	   Global symbol "%naem_of" requires explicit package name at Hierarchy.pm line 86

       Not only is that consistency check now automatic, it's also performed
       at compile time.

       The next difference is even more important and beneficial. Instead of
       blessing an empty anonymous hash as the new object:

	   my $new_object = bless {}, $class;

       the inside-out constructor blesses an empty anonymous scalar:

	   my $new_object = bless \do{my $anon_scalar}, $class;

       That odd-looking "\do{my $anon_scalar}" construct is needed because
       there's no built-in syntax in Perl for creating a reference to an
       anonymous scalar; you have to roll-your-own.

       The anonymous scalar is immediately passed to bless, which anoints it
       as an object of the appropriate class. The resulting object reference
       is then stored in $new_object.

       Once the object exists, it's used to create a unique key ("ident
       $new_object") under which each attribute that belongs to the object
       will be stored (e.g. $root_of{ident $new_object} or $name_of{ident
       $self}). The "ident()" utility that produces this unique key is
       provided by the Class::Std module and is identical in effect to the
       "refaddr()" function in the standard Scalar::Util module.

       To recap: every inside-out object is a blessed scalar, and
       has--intrinsic to it--a unique identifying integer. That integer can be
       obtained from the object reference itself, and then used to access a
       unique entry for the object in each of the class's attribute hashes.

       This means that every inside-out object is nothing more than an
       unintialized scalar. When your constructor passes a new inside-out
       object back to the client code, all that comes back is an empty scalar,
       which makes it impossible for that client code to gain direct access to
       the object's internal state.

       Of the several popular methods of reliably enforcing encapsulation in
       Perl, inside-out objects are also by far the cheapest. The run-time
       performance of inside-out classes is effectively identical to that of
       regular hash-based classes. In particular, in both schemes, every
       attribute access requires only a single hash look-up. The only
       appreciable difference in speed occurs when an inside-out object is
       destroyed.

       Hash-based classes usually don't even have destructors. When the
       object's reference count decrements to zero, the hash is automatically
       reclaimed, and any data structures stored inside the hash are likewise
       cleaned up. This works so well that many OO Perl programmers find they
       never need to write a "DESTROY()" method; Perl's built-in garbage
       collection handles everything just fine. In fact, the only time a
       destructor is needed is when objects have to manage resources outside
       that are not actually located inside the object, resources that need to
       be separately deallocated.

       But the whole point of an inside-out object is that its attributes are
       stored in allocated hashes that are not actually located inside the
       object. That's precisely how it achieves secure encapsulation: by not
       sending the attributes out into the client code.

       Unfortunately, that means when an inside-out object is eventually
       garbage collected, the only storage that is reclaimed is the single
       blessed scalar implementing the object. The object's attributes are
       entirely unaffected by the object's deallocation, because the
       attributes are not inside the object, nor are they referred to by it in
       any way.

       Instead, the attributes are referred to by the various attribute hashes
       in which they're stored. And since those hashes will continue to exist
       until the end of the program, the defunct object's orphaned attributes
       will likewise continue to exist, safely nestled inside their respective
       hashes, but now untended by any object. In other words, when an inside-
       out object dies, its associated attribute hashes leak memory.

       The solution is simple. Every inside-out class has to provide a
       destructor that "manually" cleans up the attributes of the object being
       destructed:

	   package File::Hierarchy;
	   {
	       # Objects of this class have the following attributes...
	       my %root_of;   # The root directory of the file hierarchy
	       my %files_of;  # Array storing object for each file in root directory

	       # Constructor takes path of file system root directory...
	       sub new {
		   # As before
	       }

	       # Retrieve files from root directory...
	       sub get_files {
		   # As before
	       }

	       # Clean up attributes when object is destroyed...
	       sub DESTROY {
		   my ($self) = @_;

		   delete $root_of{ident $self};
		   delete $files_of{ident $self};
	       }
	   }

       The obligation to provide a destructor like this in every inside-out
       class can be mildly irritating, but it is still a very small price to
       pay for the considerable benefits that the inside-out approach
       otherwise provides for free. And the irritation can easily be
       eliminated by using the appropriate class construction tools. See
       below.

   Automating Inside-Out Classes
       Perhaps the most annoying part about building classes in Perl (no
       matter how the objects are implemented) is that the basic structure of
       every class is more or less identical. For example, the implementation
       of the "File::Hierarchy::File" class used in "File::Hierarchy" looks
       like this:

	   package File::Hierarchy::File;
	   {
	       # Objects of this class have the following attributes...
	       my %name_of;  # the name of the file

	       # Constructor takes name of file...
	       sub new {
		   my ($class, $filename) = @_;

		   # Bless a scalar to instantiate the new object...
		   my $new_object = bless \do{my $anon_scalar}, $class;

		   # Initialize the object's "name" attribute...
		   $name_of{ident $new_object} = $filename;

		   return $new_object;
	       }

	       # Retrieve name of file...
	       sub get_name {
		   my ($self) = @_;

		   return $name_of{ident $self};
	       }

	       # Clean up attributes when object is destroyed...
	       sub DESTROY {
		   my ($self) = @_;

		   delete $name_of{ident $self};
	       }
	   }

       Apart from the actual names of the attributes, and their accessor
       methods, that's exactly the same structure, and even the same code, as
       in the "File::Hierarchy" class.

       Indeed, the standard infrastructure of every inside-out class looks
       exactly the same. So it makes sense not to have to rewrite that
       standard infrastructure code in every separate class.

       That's precisely what is module does: it implements the necessary
       infrastructure for inside-out objects. See below.

INTERFACE
   Exported subroutines
       "ident()"
	   Class::Std always exports a subroutine called "ident()". This
	   subroutine returns a unique integer ID for any object passed to it.

   Non-exported subroutines
       "Class::Std::initialize()"
	   This subroutine sets up all the infrastructure to support your
	   Class::Std- based class. It is usually called automatically in a
	   "CHECK" block, or (if the "CHECK" block fails to run -- under
	   "mod_perl" or "require Class::Std" or "eval "..."") during the
	   first constructor call made to a Class::Std-based object.

	   In rare circumstances, you may need to call this subroutine
	   directly yourself.  Specifically, if you set up cumulative,
	   restricted, private, or automethodical class methods (see below),
	   and call any of them before you create any objects, then you need
	   to call "Class::Std::initialize()" first.

   Methods created automatically
       The following subroutines are installed in any class that uses the
       Class::Std module.

       "new()"
	   Every class that loads the Class::Std module automatically has a
	   "new()" constructor, which returns an inside-out object (i.e. a
	   blessed scalar).

	       $obj = MyClass->new();

	   The constructor can be passed a single argument to initialize the
	   object. This argument must be a hash reference.

	       $obj = MyClass->new({ name=>'Foo', location=>'bar' });

	   See the subsequent descriptions of the "BUILD()" and "START()"
	   methods and ":ATTR()" trait, for an explanation of how the contents
	   of this optional hash can be used to initialize the object.

	   It is almost always an error to implement your own "new()" in any
	   class that uses Class::Std. You almost certainly want to write a
	   "BUILD()" or "START()" method instead. See below.

       "DESTROY()"
	   Every class that loads the Class::Std module automatically has a
	   "DESTROY()" destructor, which automatically cleans up any
	   attributes declared with the ":ATTR()" trait (see below).

	   It is almost always an error to write your own "DESTROY()" in any
	   class that uses Class::Std. You almost certainly want to write your
	   own "DEMOLISH()" instead. See below.

       "AUTOLOAD()"
	   Every class that loads the Class::Std module automatically has an
	   "AUTOLOAD()" method, which implements the "AUTOMETHOD()" mechanism
	   described below.

	   It is almost always an error to write your own "AUTOLOAD()" in any
	   class that uses Class::Std. You almost certainly want to write your
	   own "AUTOMETHOD()" instead.

       "_DUMP()"
	   This method returns a string that represents the internal state
	   (i.e. the attribute values) of the object on which it's called.
	   Only those attributes which are marked with an ":ATTR" (see below)
	   are reported. Attribute names are reported only if they can be
	   ascertained from an ":init_arg", ":get", or ":set" option within
	   the ":ATTR()".

	   Note that "_DUMP()" is not designed to support full
	   serialization/deserialization of objects. See the separate
	   Class::Std::Storable module (on CPAN) for that.

   Methods that can be supplied by the developer
       The following subroutines can be specified as standard methods of a
       Class::Std class.

       "BUILD()"
	   When the "new()" constructor of a Class::Std class is called, it
	   automatically calls every method named "BUILD()" in all the classes
	   in the new object's hierarchy. That is, when the constructor is
	   called, it walks the class's inheritance tree (from base classes
	   downwards) and calls every "BUILD()" method it finds along the way.

	   This means that, to initialize any class, you merely need to
	   provide a "BUILD()" method for that class. You don't have to worry
	   about ensuring that any ancestral "BUILD()" methods also get
	   called; the constructor will take care of that.

	   Each "BUILD()" method is called with three arguments: the invocant
	   object, the identifier number of that object, and a reference to (a
	   customized version of) the hash of arguments that was originally
	   passed to the constructor:

	       sub BUILD {
		   my ($self, $ident, $args_ref) = @_;
		   ...
	       }

	   The argument hash is a "customized version" because the module
	   automatically does some fancy footwork to ensure that the arguments
	   are the ones appropriate to the class itself. That's because
	   there's a potential for collisions when Class::Std classes are used
	   in a hierarchy.

	   One of the great advantages of using inside-out classes instead of
	   hash-based classes is that an inside-out base class and an inside-
	   out derived class can then each have an attribute of exactly the
	   same name, which are stored in separate lexical hashes in separate
	   scopes. In a hash-based object that's impossible, because the
	   single hash can't have two attributes with the same key.

	   But that very advantage also presents something of a problem when
	   constructor arguments are themselves passed by hash. If two or more
	   classes in the name hierarchy do happen to have attributes of the
	   same name, the constructor will need two or more initializers with
	   the name key. Which a single hash can't provide.

	   The solution is to allow initializer values to be partitioned into
	   distinct sets, each uniquely named, and which are then passed to
	   the appropriate base class. The easiest way to accomplish that is
	   to pass in a hash of hashes, where each top level key is the name
	   of one of the base classes, and the corresponding value is a hash
	   of initializers specifically for that base class.

	   For example:

	       package Client;
	       use Class::Std::Utils;
	       {
		   my %client_num_of :ATTR;  # Every client has a basic ID number
		   my %name_of	     :ATTR;

		   sub BUILD {
		       my ($self, $ident, $arg_ref) = @_;

		       $client_num_of{$ident} = $arg_ref->{'Client'}{client_num};
		       $name_of{$ident}	      = $arg_ref->{'Client'}{client_name};
		   }
	       }

	       package Client::Corporate;
	       use base qw( Client );
	       use Class::Std::Utils;
	       {
		   my %client_num_of;	  # Corporate clients have an additional ID number
		   my %corporation_of;
		   my %position_of;

		   sub BUILD {
		       my ($self, $ident, $arg_ref) = @_;

		       $client_num_of{$ident}
			   = $arg_ref->{'Client::Corporate'}{client_num};
		       $corporation_of{$ident}
			   = $arg_ref->{'Client::Corporate'}{corp_name};
		       $position_of{$ident}
			   = $arg_ref->{'Client::Corporate'}{position};
		   }
	       }

	       # and later...

	       my $new_client
		   = Client::Corporate->new( {
		       'Client' => {
			   client_num  => '124C1',
			   client_name => 'Humperdinck',
		       },
		       'Client::Corporate' => {
			   client_num  => 'F_1692',
			   corp_name   => 'Florin',
			   position    => 'CEO',
		       },
		   });

	   Now each class's "BUILD()" method picks out only the initializer
	   sub-hash whose key is that class's own name. Since every class name
	   is different, the top-level keys of this multi-level initializer
	   hash are guaranteed to be unique. And since no single class can
	   have two identically named attributes, the keys of each second-
	   level hash will be unique as well. If two classes in the hierarchy
	   both need an initializer of the same name (e.g. 'client_num'),
	   those two hash entries will now be in separate sub-hashes, so they
	   will never clash.

	   Class::Std provides an even more sophisticated variation on this
	   functionality, which is generally much more convenient for the
	   users of classes. Classes that use Class::Std infrastructure allow
	   both general and class-specific initializers in the initialization
	   hash. Clients only need to specify classes for those initializers
	   whose names actually are ambiguous. Any other arguments can just be
	   passed directly in the top-level hash:

	       my $new_client
		   = Client::Corporate->new( {
		       client_name => 'Humperdinck',
		       corp_name   => 'Florin',
		       position	   => 'CEO',

		       'Client'		   => { client_num  => '124C1'	},
		       'Client::Corporate' => { client_num  => 'F_1692' },
		   });

	   Class::Std also makes it easy for each class's "BUILD()" to access
	   these class-specific initializer values. Before each "BUILD()" is
	   invoked, the nested hash whose key is the same as the class name is
	   flattened back into the initializer hash itself. That is,
	   "Client::BUILD()" is passed the hash:

	       {
		   client_name => 'Humperdinck',
		   corp_name   => 'Florin',
		   position    => 'CEO',
		   client_num  => '124C1',   # Flattened from 'Client' nested subhash

		   'Client'	       => { client_num	=> '124C1'  },
		   'Client::Corporate' => { client_num	=> 'F_1692' },
	       }

	   whereas "Client::Corporate::BUILD()" is passed the hash:

	       {
		   client_name => 'Humperdinck',
		   corp_name   => 'Florin',
		   position    => 'CEO',
		   client_num  => 'F_1692',   # Flattened from 'Client::Corporate' subhash

		   'Client'	       => { client_num	=> '124C1'  },
		   'Client::Corporate' => { client_num	=> 'F_1692' },
	       }

	   This means that the "BUILD()" method for each class can just assume
	   that the correct class-specific initializer values will available
	   at the top level of the hash. For example:

		   sub Client::BUILD {
		       my ($self, $ident, $arg_ref) = @_;

		       $client_num_of{$ident} = $arg_ref->{client_num};	   # '124C1'
		       $name_of{$ident}	      = $arg_ref->{client_name};
		   }

		   sub Client::Corporate::BUILD {
		       my ($self, $ident, $arg_ref) = @_;

		       $client_num_of{$ident}  = $arg_ref->{client_num};   # 'F_1692'
		       $corporation_of{$ident} = $arg_ref->{corp_name};
		       $position_of{$ident}    = $arg_ref->{position};
		   }

	   Both classes use the "$arg_ref->{client_num}" initializer value,
	   but Class::Std automatically arranges for that value to be the
	   right one for each class.

	   Also see the ":ATTR()" marker (described below) for a simpler way
	   of initializing attributes.

       "START()"
	   Once all the "BUILD()" methods of a class have been called and any
	   initialization values or defaults have been subsequently applied to
	   uninitialized attributes, Class::Std arranges for any "START()"
	   methods in the class's hierarchy to be called befre the constructor
	   finishes.  That is, after the build and default initialization
	   processes are complete, the constructor walks down the class's
	   inheritance tree a second time and calls every "START()" method it
	   finds along the way.

	   As with "BUILD()", each "START()" method is called with three
	   arguments: the invocant object, the identifier number of that
	   object, and a reference to (a customized version of) the hash of
	   arguments that was originally passed to the constructor.

	   The main difference between a "BUILD()" method and a "START()"
	   method is that a "BUILD()" method runs before any attribute of the
	   class is auto-initialized or default-initialized, whereas a
	   "START()" method runs after all the attributes of the class
	   (including attributes in derived classes) have been initialized in
	   some way. So if you want to pre-empt the initialization process,
	   write a "BUILD()". But if you want to do something with the newly
	   created and fully initialized object, write a "START()" instead. Of
	   course, any class can define both a "BUILD()" and a "START()"
	   method, if that happens to be appropriate.

       "DEMOLISH()"
	   The "DESTROY()" method that is automatically provided by Class::Std
	   ensures that all the marked attributes (see the ":ATTR()" marker
	   below) of an object, from all the classes in its inheritance
	   hierarchy, are automatically cleaned up.

	   But, if a class requires other destructor behaviours (e.g. closing
	   filehandles, decrementing allocation counts, etc.) then you may
	   need to specify those explicitly.

	   Whenever an object of a Class::Std class is destroyed, the
	   "DESTROY()" method supplied by Class::Std automatically calls every
	   method named "DEMOLISH()" in all the classes in the new object's
	   hierarchy. That is, when the destructor is called, it walks the
	   class's inheritance tree (from derived classes upwards) and calls
	   every "DEMOLISH()" method it finds along the way.

	   This means that, to clean up any class, you merely need to provide
	   a "DEMOLISH()" method for that class. You don't have to worry about
	   ensuring that any ancestral "DEMOLISH()" methods also get called;
	   the destructor will take care of that.

	   Each "DEMOLISH()" method is called with two arguments: the invocant
	   object, and the identifier number of that object. For example:

	       sub DEMOLISH {
		   my ($self, $ident) = @_;

		   $filehandle_of{$ident}->flush();
		   $filehandle_of{$ident}->close();
	       }

	   Note that the attributes of the object are cleaned up after the
	   "DEMOLISH()" method is complete, so they may still be used within
	   that method.

       "AUTOMETHOD()"
	   There is a significant problem with Perl's built-in "AUTOLOAD"
	   mechanism: there's no way for a particular "AUTOLOAD()" to say
	   "no".

	   If two or more classes in a class hierarchy have separate
	   "AUTOLOAD()" methods, then the one belonging to the left-most-
	   depth-first class in the inheritance tree will always be invoked in
	   preference to any others.  If it can't handle a particular call,
	   the call will probably fail catastrophically. This means that
	   derived classes can't always be used in place of base classes (a
	   feature known as "Liskov substitutability") because their inherited
	   autoloading behaviour may be pre-empted by some other unrelated
	   base class on their left in the hierarchy.

	   Class::Std provides a mechanism that solves this problem: the
	   "AUTOMETHOD" method. An AUTOMETHOD() is expected to return either a
	   handler subroutine that implements the requested method
	   functionality, or else an "undef" to indicate that it doesn't know
	   how to handle the request. Class::Std then coordinates every
	   "AUTOMETHOD()" in an object's hierarchy, trying each one in turn
	   until one of them produces a suitable handler.

	   The advantage of this approach is that the first "AUTOMETHOD()"
	   that's invoked doesn't have to disenfranchise every other
	   "AUTOMETHOD()" in the hierarchy. If the first one can't handle a
	   particular method call, it simply declines it and Class::Std tries
	   the next candidate instead.

	   Using "AUTOMETHOD()" instead of "AUTOLOAD()" makes a class cleaner,
	   more robust, and less disruptive in class hierarchies.  For
	   example:

	       package Phonebook;
	       use Class::Std;
	       {
		   my %entries_of : ATTR;

		   # Any method call is someone's name:
		   # so store their phone number or get it...
		   sub AUTOMETHOD {
		       my ($self, $ident, $number) = @_;

		       my $subname = $_;   # Requested subroutine name is passed via $_

		       # Return failure if not a get_<name> or set_<name>
		       # (Next AUTOMETHOD() in hierarchy will then be tried instead)...
		       my ($mode, $name) = $subname =~ m/\A ([gs]et)_(.*) \z/xms
			   or return;

		       # If get_<name>, return a handler that just returns the old number...
		       return sub { return $entries_of{$ident}->{$name}; }
			   if $mode eq 'get';

		       # Otherwise, set_<name>, so return a handler that
		       # updates the entry and then returns the old number...
		       return sub {
			   $entries_of{$ident}->{$name} = $number;
			   return;
		       };
		   }
	       }

	       # and later...

	       my $lbb = Phonebook->new();

	       $lbb->set_Jenny(867_5309);
	       $lbb->set_Glenn(736_5000);

	       print $lbb->get_Jenny(), "\n";
	       print $lbb->get_Glenn(), "\n";

	   Note that, unlike "AUTOLOAD()", an "AUTOMETHOD()" is called with
	   both the invocant and the invocant's unique "ident" number,
	   followed by the actual arguments that were passed to the method.

	   Note too that the name of the method being called is passed as $_
	   instead of $AUTOLOAD, and does not have the class name prepended to
	   it, so you don't have to strip that name off the front like almost
	   everyone almost always does in their "AUTOLOAD()". If your
	   "AUTOMETHOD()" also needs to access the $_ from the caller's scope,
	   that's still available as $CALLER::_.

   Variable traits that can be ascribed
       The following markers can be added to the definition of any hash used
       as an attribute storage within a Class::Std class

       ":ATTR()"
	   This marker can be used to indicate that a lexical hash is being
	   used to store one particular attribute of all the objects of the
	   class. That is:

	       package File::Hierarchy;
	       {
		   my %root_of	:ATTR;
		   my %files_of :ATTR;

		   # etc.
	       }

	       package File::Hierarchy::File;
	       {
		   my %name_of;	 :ATTR;

		   # etc.
	       }

	   Adding the ":ATTR" marker to an attribute hash ensures that the
	   corresponding attribute belonging to each object of the class is
	   automatically cleaned up when the object is destroyed.

	   The ":ATTR" marker can also be given a number of options which
	   automate other attribute-related behaviours. Each of these options
	   consists of a key/value pair, which may be specified in either Perl
	   5 "fat comma" syntax ( "key => 'value'" ) or in one of the Perl 6
	   option syntaxes ( ":key<value>" or ":key('value')" or
	   ":keyAXvalueAX").

	   Note that, due to a limitation in Perl itself, the complete ":ATTR"
	   marker, including its options must appear on a single line.
	   interpolate variables into the option values

	   ":ATTR( :init_arg<initializer_key> )"
	       This option tells Class::Std which key in the constructor's
	       initializer hash holds the value with which the marked
	       attribute should be initialized. That is, instead of writing:

		   my %rank_of :ATTR;

		   sub BUILD {
		       my ($self, $ident, $arg_ref) = @_;

		       $rank_of{$ident} = $arg_ref->{rank};
		   }

	       you can achieve the same initialization, by having Class::Std
	       automatically pull that entry out of the hash and store it in
	       the right attribute:

		   my %rank_of :ATTR( :init_arg<rank> );

		   # No BUILD() method required

	   ":ATTR( :default<compile_time_default_value> )"
	       If a marked attribute is not initialized (either directly
	       within a "BUILD()", or automatically via an ":init_arg"
	       option), the constructor supplied by Class::Std checks to see
	       if a default value was specified for that attribute. If so,
	       that value is assigned to the attribute.

	       So you could replace:

		   my %seen_of :ATTR;

		   sub BUILD {
		       my ($self, $ident, $arg_ref) = @_;

		       $seen_of{$ident} = 0;  # Not seen yet
		   }

	       with:

		   my %seen_of :ATTR( :default(0) );

		   # No BUILD() required

	       Note that only literal strings and numbers can be used as
	       default values. A common mistake is to write:

		   my %seen_of :ATTR( :default($some_variable) );

	       But variables like this aren't interpolated into ":ATTR"
	       markers (this is a limitation of Perl, not Class::Std).

	       If your attribute needs something more complex, you will have
	       to default initialize it in a "START()" method:

		   my %seen_of :ATTR;

		   sub START {
		       my ($self, $id, $args_ref) = @_;

		       if (!defined $seen_of{$id}) {
			   $seen_of{$id} = $some_variable;
		       }
		   }

	   ":ATTR( :get<name> )"
	       If the ":get" option is specified, a read accessor is created
	       for the corresponding attribute. The name of the accessor is
	       "get_" followed by whatever name is specified as the value of
	       the ":get" option. For example, instead of:

		   my %current_count_of :ATTR;

		   sub get_count {
		       my ($self) = @_;

		       return $current_count_of{ident($self)};
		   }

	       you can just write:

		   my %count_of :ATTR( :get<count> );

	       Note that there is no way to prevent Class::Std adding the
	       initial "get_" to each accessor name it creates. That's what
	       "standard" means. See Chapter 15 of Perl Best Practices
	       (O'Reilly, 2005) for a full discussion on why accessors should
	       be named this way.

	   ":ATTR( :set<name> )"
	       If the ":set" option is specified, a write accessor is created
	       for the corresponding attribute. The name of the accessor is
	       "set_" followed by whatever name is specified as the value of
	       the ":set" option. For example, instead of:

		   my %current_count_of :ATTR;

		   sub set_count {
		       my ($self, $new_value) = @_;

		       croak "Missing new value in call to 'set_count' method"
			   unless @_ == 2;

		       $current_count_of{ident($self)} = $new_value;
		   }

	       you can just write:

		   my %count_of :ATTR( :set<count> );

	       Note that there is no way to prevent Class::Std adding the
	       initial "set_" to each accessor name it creates. Nor is there
	       any way to create a combined "getter/setter" accessor. See
	       Chapter 15 of Perl Best Practices (O'Reilly, 2005) for a full
	       discussion on why accessors should be named and implemented
	       this way.

	   ":ATTR( :name<name> )"
	       Specifying the ":name" option is merely a convenient shorthand
	       for specifying all three of ":get", ":set", and ":init_arg".

	   You can, of course, specify two or more arguments in a single
	   ":ATTR()" specification:

	       my %rank_of : ATTR( :init_arg<starting_rank>  :get<rank>	 :set<rank> );

       ":ATTRS()"
	   This is just another name for the ":ATTR" marker (see above). The
	   plural form is convenient when you want to specify a series of
	   attribute hashes in the same statement:

	       my (
		   %name_of,
		   %rank_of,
		   %snum_of,
		   %age_of,
		   %unit_of,
		   %assignment_of,
		   %medals_of,
	       ) : ATTRS;

   Method traits that can be ascribed
       The following markers can be added to the definition of any subroutine
       used as a method within a Class::Std class

       ":RESTRICTED()"
       ":PRIVATE()"
	   Occasionally, it is useful to be able to create subroutines that
	   can only be accessed within a class's own hierarchy (that is, by
	   derived classes). And sometimes it's even more useful to be able to
	   create methods that can only be called within a class itself.

	   Typically these types of methods are utility methods: subroutines
	   that provide some internal service for a class, or a class
	   hierarchy.  Class::Std supports the creation of these kinds of
	   methods by providing two special markers: ":RESTRICTED()" and
	   ":PRIVATE()".

	   Methods marked ":RESTRICTED()" are modified at the end of the
	   compilation phase so that they throw an exception when called from
	   outside a class's hierarchy. Methods marked ":PRIVATE()" are
	   modified so that they throw an exception when called from outside
	   the class in which they're declared.

	   For example:

	       package DogTag;
	       use Class::Std;
	       {
		   my %ID_of   : ATTR;
		   my %rank_of : ATTR;

		   my $ID_num = 0;

		   sub _allocate_next_ID : RESTRICTED {
		       my ($self) = @_;
		       $ID_of{ident $self} = $ID_num++;
		       return;
		   }

		   sub _check_rank : PRIVATE {
		       my ($rank) = @_;
		       return $rank if $VALID_RANK{$rank};
		       croak "Unknown rank ($rank) specified";
		   }

		   sub BUILD {
		       my ($self, $ident, $arg_ref) = @_;

		       $self->_allocate_next_ID();
		       $rank_of{$ident} = _check_rank($arg_ref->{rank});
		   }
	       }

	   Of course, this code would run exactly the same without the
	   ":RESTRICTED()" and ":PRIVATE()" markers, but they ensure that any
	   attempt to call the two subroutines inappropriately:

	       package main;

	       my $dogtag = DogTag->new({ rank => 'PFC' });

	       $dogtag->_allocate_next_ID();

	   is suitably punished:

	       Can't call restricted method DogTag::_allocate_next_ID() from class main

       ":CUMULATIVE()"
	   One of the most important advantages of using the "BUILD()" and
	   "DEMOLISH()" mechanisms supplied by Class::Std is that those
	   methods don't require nested calls to their ancestral methods, via
	   the "SUPER" pseudo-class. The constructor and destructor provided
	   by Class::Std take care of the necessary redispatching
	   automatically. Each "BUILD()" method can focus solely on its own
	   responsibilities; it doesn't have to also help orchestrate the
	   cumulative constructor effects across the class hierarchy by
	   remembering to call "$self->SUPER::BUILD()".

	   Moreover, calls via "SUPER" can only ever call the method of
	   exactly one ancestral class, which is not sufficient under multiple
	   inheritance.

	   Class::Std provides a different way of creating methods whose
	   effects accumulate through a class hierarchy, in the same way as
	   those of "BUILD()" and "DEMOLISH()" do. Specifically, the module
	   allows you to define your own "cumulative methods".

	   An ordinary non-cumulative method hides any method of the same name
	   inherited from any base class, so when a non-cumulative method is
	   called, only the most-derived version of it is ever invoked. In
	   contrast, a cumulative method doesn't hide ancestral methods of the
	   same name; it assimilates them. When a cumulative method is called,
	   the most-derived version of it is invoked, then any parental
	   versions, then any grandparental versions, etc. etc, until every
	   cumulative method of the same name throughout the entire hierarchy
	   has been called.

	   For example, you could define a cumulative "describe()" method to
	   the various classes in a simple class hierarchy like so:

	       package Wax::Floor;
	       use Class::Std;
	       {
		   my %name_of	  :ATTR( init_arg => 'name'   );
		   my %patent_of  :ATTR( init_arg => 'patent' );

		   sub describe :CUMULATIVE {
		       my ($self) = @_;

		       print "The floor wax $name_of{ident $self} ",
			     "(patent: $patent_of{ident $self})\n";

		       return;
		   }
	       }

	       package Topping::Dessert;
	       use Class::Std;
	       {
		   my %name_of	   :ATTR( init_arg => 'name'	);
		   my %flavour_of  :ATTR( init_arg => 'flavour' );

		   sub describe :CUMULATIVE {
		       my ($self) = @_;

		       print "The dessert topping $name_of{ident $self} ",
			     "with that great $flavour_of{ident $self} taste!\n";

		       return;
		   }
	       }

	       package Shimmer;
	       use base qw( Wax::Floor	Topping::Dessert );
	       use Class::Std;
	       {
		   my %name_of	  :ATTR( init_arg => 'name'   );
		   my %patent_of  :ATTR( init_arg => 'patent' );

		   sub describe :CUMULATIVE {
		       my ($self) = @_;

		       print "New $name_of{ident $self} ",
			     "(patent: $patent_of{ident $self})\n",
			     "Combining...\n";

		       return;
		   }
	       }

	   Because the various "describe()" methods are marked as being
	   cumulative, a subsequent call to:

	       my $product
		   = Shimmer->new({
			 name	 => 'Shimmer',
			 patent	 => 1562516251,
			 flavour => 'Vanilla',
		     });

	       $product->describe();

	   will work its way up through the classes of Shimmer's inheritance
	   tree (in the same order as a destructor call would), calling each
	   "describe()" method it finds along the way. So the single call to
	   "describe()" would invoke the corresponding method in each class,
	   producing:

	       New Shimmer (patent: 1562516251)
	       Combining...
	       The floor wax Shimmer (patent: 1562516251)
	       The dessert topping Shimmer with that great Vanilla taste!

	   Note that the accumulation of "describe()" methods is hierarchical,
	   and dynamic in nature. That is, each class only sees those
	   cumulative methods that are defined in its own package or in one of
	   its ancestors.  So calling the same "describe()" on a base class
	   object:

	       my $wax
		   = Wax::Floor->new({ name=>'Shimmer ', patent=>1562516251 });

	       $wax->describe();

	   only invokes the corresponding cumulative methods from that point
	   on up the hierarchy, and hence only prints:

	       The floor wax Shimmer (patent: 1562516251)

	   Cumulative methods also accumulate their return values. In a list
	   context, they return a (flattened) list that accumulates the lists
	   returned by each individual method invoked.

	   In a scalar context, a set of cumulative methods returns an object
	   that, in a string context, concatenates individual scalar returns
	   to produce a single string. When used as an array reference that
	   same scalar-context-return object acts like an array of the list
	   context values. When used as a hash reference, the object acts like
	   a hash whose keys are the classnames from the object's hierarchy,
	   and whose corresponding values are the return values of the
	   cumulative method from that class.

	   For example, if the classes each have a cumulative method that
	   returns their list of sales features:

	       package Wax::Floor;
	       use Class::Std;
	       {
		   sub feature_list :CUMULATIVE {
		       return ('Long-lasting', 'Non-toxic', 'Polymer-based');
		   }
	       }

	       package Topping::Dessert;
	       use Class::Std;
	       {
		   sub feature_list :CUMULATIVE {
		       return ('Low-carb', 'Non-dairy', 'Sugar-free');
		   }
	       }

	       package Shimmer;
	       use Class::Std;
	       use base qw( Wax::Floor	Topping::Dessert );
	       {
		   sub feature_list :CUMULATIVE {
		       return ('Multi-purpose', 'Time-saving', 'Easy-to-use');
		   }
	       }

	   then calling feature_list() in a list context:

	       my @features = Shimmer->feature_list();
	       print "Shimmer is the @features alternative!\n";

	   would produce a concatenated list of features, which could then be
	   interpolated into a suitable sales-pitch:

	       Shimmer is the Multi-purpose Time-saving Easy-to-use
	       Long-lasting Non-toxic Polymer-based Low-carb Non-dairy
	       Sugar-free alternative!

	   It's also possible to specify a set of cumulative methods that
	   start at the base class(es) of the hierarchy and work downwards,
	   the way BUILD() does. To get that effect, you simply mark each
	   method with :CUMULATIVE(BASE FIRST), instead of just :CUMULATIVE.
	   For example:

	       package Wax::Floor;
	       use Class::Std;
	       {
		   sub active_ingredients :CUMULATIVE(BASE FIRST) {
		       return "\tparadichlorobenzene, cyanoacrylate, peanuts\n";
		   }
	       }

	       package Topping::Dessert;
	       use Class::Std;
	       {
		   sub active_ingredients :CUMULATIVE(BASE FIRST) {
		       return "\tsodium hypochlorite, isobutyl ketone, ethylene glycol\n";
		   }
	       }

	       package Shimmer;
	       use Class::Std;
	       use base qw( Wax::Floor	Topping::Dessert );

	       {
		   sub active_ingredients :CUMULATIVE(BASE FIRST) {
		       return "\taromatic hydrocarbons, xylene, methyl mercaptan\n";
		   }
	       }

	   So a scalar-context call to active_ingredients():

	       my $ingredients = Shimmer->active_ingredients();
	       print "May contain trace amounts of:\n$ingredients";

	   would start in the base classes and work downwards, concatenating
	   base- class ingredients before those of the derived class, to
	   produce:

	       May contain trace amounts of:
		   paradichlorobenzene, cyanoacrylate, peanuts
		   sodium hypochlorite, isobutyl ketone, ethylene glycol
		   aromatic hydrocarbons, xylene, methyl mercaptan

	   Or, you could treat the return value as a hash:

	       print Data::Dumper::Dumper \%{$ingredients};

	   and see which ingredients came from where:

	       $VAR1 = {
		  'Shimmer'
		       => 'aromatic hydrocarbons, xylene, methyl mercaptan',

		  'Topping::Dessert'
		       => 'sodium hypochlorite, isobutyl ketone, ethylene glycol',

		   'Wax::Floor'
		       => 'Wax: paradichlorobenzene,  hydrogen peroxide, cyanoacrylate',
	       };

	   Note that you can't specify both ":CUMULATIVE" and
	   ":CUMULATIVE(BASE FIRST)" on methods of the same name in the same
	   hierarchy. The resulting set of methods would have no well-defined
	   invocation order, so Class::Std throws a compile-time exception
	   instead.

       ":STRINGIFY"
	   If you define a method and add the ":STRINGIFY" marker then that
	   method is used whenever an object of the corresponding class needs
	   to be coerced to a string. In other words, instead of:

	       # Convert object to a string...
	       sub as_str {
		   ...
	       }

	       # Convert object to a string automatically in string contexts...
	       use overload (
		   q{""}    => 'as_str',
		   fallback => 1,
	       );

	   you can just write:

	       # Convert object to a string (automatically in string contexts)...
	       sub as_str : STRINGIFY {
		   ...
	       }

       ":NUMERIFY"
	   If you define a method and add the ":NUMERIFY" marker then that
	   method is used whenever an object of the corresponding class needs
	   to be coerced to a number. In other words, instead of:

	       # Convert object to a number...
	       sub as_num {
		   ...
	       }

	       # Convert object to a string automatically in string contexts...
	       use overload (
		   q{0+}    => 'as_num',
		   fallback => 1,
	       );

	   you can just write:

	       # Convert object to a number (automatically in numeric contexts)...
	       sub as_num : NUMERIFY {
		   ...
	       }

       ":BOOLIFY"
	   If you define a method and add the ":BOOLIFY" marker then that
	   method is used whenever an object of the corresponding class needs
	   to be coerced to a boolean value. In other words, instead of:

	       # Convert object to a boolean...
	       sub as_bool {
		   ...
	       }

	       # Convert object to a boolean automatically in boolean contexts...
	       use overload (
		   q{bool}    => 'as_bool',
		   fallback => 1,
	       );

	   you can just write:

	       # Convert object to a boolean (automatically in boolean contexts)...
	       sub as_bool : BOOLIFY {
		   ...
	       }

       ":SCALARIFY"
       ":ARRAYIFY"
       ":HASHIFY"
       ":GLOBIFY"
       ":CODIFY"
	   If a method is defined with one of these markers, then it is
	   automatically called whenever an object of that class is treated as
	   a reference of the corresponding type.

	   For example, instead of:

	       sub as_hash {
		   my ($self) = @_;

		   return {
		       age	=> $age_of{ident $self},
		       shoesize => $shoe_of{ident $self},
		   };
	       }

	       use overload (
		   '%{}'    => 'as_hash',
		   fallback => 1,
	       );

	   you can just write:

	       sub as_hash : HASHIFY {
		   my ($self) = @_;

		   return {
		       age	=> $age_of{ident $self},
		       shoesize => $shoe_of{ident $self},
		   };
	       }

	   Likewise for methods that allow an object to be treated as a scalar
	   reference (":SCALARIFY"), a array reference (":ARRAYIFY"), a
	   subroutine reference (":CODIFY"), or a typeglob reference
	   (":GLOBIFY").

DIAGNOSTICS
       Can't find class %s
	   You tried to call the Class::Std::new() constructor on a class that
	   isn't built using Class::Std. Did you forget to write "use
	   Class::Std" after the package declaration?

       Argument to %s->new() must be hash reference
	   The constructors created by Class::Std require all initializer
	   values to be passed in a hash, but you passed something that wasn't
	   a hash.  Put your constructor arguments in a hash.

       Missing initializer label for %s: %s
	   You specified that one or more attributes had initializer values
	   (using the "init" argument inside the attribute's "ATTR" marker),
	   but then failed to pass in the corresponding initialization value.
	   Often this happens because the initialization value was passed, but
	   the key specifying the attribute name was misspelled.

       Can't make anonymous subroutine cumulative
	   You attempted to use the ":CUMULATIVE" marker on an anonymous
	   subroutine.	But that marker can only be applied to the named
	   methods of a class. Convert the anonymous subroutine to a named
	   subroutine, or find some other way to make it interoperate with
	   other methods.

       Conflicting definitions for cumulative method: %s
	   You defined a ":CUMULATIVE" and a ":CUMULATIVE(BASE FIRST)" method
	   of the same name in two classes within the same hierarchy. Since
	   methods can only be called going strictly up through the hierarchy
	   or going strictly down through the hierarchy, specifying both
	   directions is obviously a mistake.  Either rename one of the
	   methods, or decide whether they should accumulate upwards or
	   downwards.

       Missing new value in call to 'set_%s' method
	   You called an attribute setter method without providing a new value
	   for the attribute. Often this happens because you passed an array
	   that happened to be empty. Make sure you pass an actual value.

       Can't locate %s method "%s" via package %s
	   You attempted to call a method on an object but no such method is
	   defined anywhere in the object's class hierarchy. Did you misspell
	   the method name, or perhaps misunderstand which class the object
	   belongs to?

       %s method %s declared but not defined
	   A method was declared with a ":RESTRICTED" or ":PRIVATE", like so:

	       sub foo :RESTRICTED;
	       sub bar :PRIVATE;

	   But the actual subroutine was not defined by the end of the
	   compilation phase, when the module needed it so it could be
	   rewritten to restrict or privatize it.

       Can't call restricted method %s from class %s
	   The specified method was declared with a ":RESTRICTED" marker but
	   subsequently called from outside its class hierarchy. Did you call
	   the wrong method, or the right method from the wrong place?

       Can't call private method %s from class %s
	   The specified method was declared with a ":PRIVATE" marker but
	   subsequently called from outside its own class. Did you call the
	   wrong method, or the right method from the wrong place?

       Internal error: %s
	   Your code is okay, but it uncovered a bug in the Class::Std module.
	   "BUGS AND LIMITATIONS" explains how to report the problem.

CONFIGURATION AND ENVIRONMENT
       Class::Std requires no configuration files or environment variables.

DEPENDENCIES
       Class::Std depends on the following modules:

       ·   version

       ·   Scalar::Util

       ·   Data::Dumper

INCOMPATIBILITIES
       Incompatible with the Attribute::Handlers module, since both define
       meta-attributes named :ATTR.

BUGS AND LIMITATIONS
       ·   Does not handle threading (including "fork()" under Windows).

       ·   ":ATTR" declarations must all be on the same line (due to a
	   limitation in Perl itself).

       ·   ":ATTR" declarations cannot include variables, since these are not
	   interpolated into the declaration (a limitation in Perl itself).

       Please report any bugs or feature requests to
       "bug-class-std@rt.cpan.org", or through the web interface at
       <http://rt.cpan.org>.

ALTERNATIVES
       Inside-out objects are gaining in popularity and there are now many
       other modules that implement frameworks for building inside-out
       classes. These include:

       Object::InsideOut
	   Array-based objects, with support for threading. Many excellent
	   features (especially thread-safety), but slightly less secure than
	   Class::Std, due to non-encapsulation of attribute data addressing.

       Class::InsideOut
	   A minimalist approach to building inside-out classes.

       Lexical::Attributes
	   Uses source filters to provide a near-Perl 6 approach to declaring
	   inside-out classes.

       Class::Std::Storable
	   Adds serialization/deserialization to Class::Std.

AUTHOR
       Damian Conway  "<DCONWAY@cpan.org>"

LICENCE AND COPYRIGHT
       Copyright (c) 2005, Damian Conway "<DCONWAY@cpan.org>". All rights
       reserved.

       Portions of the documentation from "Perl Best Practices" copyright (c)
       2005 by O'Reilly Media, Inc. and reprinted with permission.

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

DISCLAIMER OF WARRANTY
       BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
       FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT
       WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
       PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND,
       EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
       ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
       YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
       NECESSARY SERVICING, REPAIR, OR CORRECTION.

       IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
       WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
       REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE
       TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR
       CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
       SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
       RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
       FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
       SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
       DAMAGES.

perl v5.14.1			  2011-06-20			 Class::Std(3)
[top]

List of man pages available for Pidora

Copyright (c) for man pages and the logo by the respective OS vendor.

For those who want to learn more, the polarhome community provides shell access and support.

[legal] [privacy] [GNU] [policy] [cookies] [netiquette] [sponsors] [FAQ]
Tweet
Polarhome, production since 1999.
Member of Polarhome portal.
Based on Fawad Halim's script.
....................................................................
Vote for polarhome
Free Shell Accounts :: the biggest list on the net