Class::IntrospectionMethods - creates methods with introspection
use Class::IntrospectionMethods qw/make_methods/; make_methods ( parent, global_catalog => { name => 'metacat', list => [ [qw/foo/] => f_cat, [qw/bar baz/] => b_cat, ], } new_with_init => 'new', get_set => [ qw /foo bar baz / ]; ) ;
This module provides:
A way to set up a lot of get/set method. These get/set methods can access plain scalars, array, hash. These scalar, hash or array can be tied (See perltie) with classes specified by the user. The element of these arrays or hashes can be constrained to be object, tied scalar.
A way to later query the object or class to retrieve the list of methods (aka slots) created by this module.
A way to organize these slots in several catalogs.
When a slot contains object or tied scalars hashes or arrays, the contained object can be queried for the container object. In other words, the parent object (the one constructed by Class::IntrospectionMethods contains a child object in one of its slots either as a plain object or an object hidden behind a tied construct. Class::IntrospectionMethods will provide the child object a method to retrieve the parent object reference.
Class::IntrospectionMethods
For instance, you can use this module to create a tree where each node or leaf is an object. In this case, this module provides methods to navigate up the tree of objects with the installed "parent" method.
In other words, this module provides special methods to enable the user to navigate up or down a tree (or directed graph) using introspection (to go down) and the "parent" method to go up.
You may notice similarities between this module and Class::MethodMaker. In fact this module was written from Class::MethodMaker v1.08, but it does not provide most of the fancy methods of Class::MethodMaker. Only scalar, array and hash accessors (with their tied and objects variants) are provided.
Originally, the introspection and "parent" functionalities were implemented in Class::MethodMaker. Unfortunately, they were not accepted by Class::MethodMaker's author since they did not fit his own vision of his module (fair enough).
The old API of Class::MethodMaker is provided as deprecated methods. Using the new (and hopefully more consistent) API is prefered.
This module was forked from Class::MethodMaker v1.08. To ease migration from older project (which include a proprietary project of mine) using Class::MethodMaker to Class::IntrospectionMethods, a compatiblity mode is provided. (although some features of Class::MethodMaker will not work. See Class::IntrospectionMethods::Legacy for details)
You can use the following function to finely tune the compatibility behavior to either croak, carp (See Carp for details) or be silent.
One note: I provide backward compatibility for Class::MethodMaker v1.08 and the modification I made that were later refused. So you may notice compatibility features that do not exist in Class::MethodMaker v1.08.
behavior is either skip, carp or croak. (default is carp).
behavior
skip
carp
croak
provide_legacy_method is either 1 or 0. Default 0. When set to one, this module will provide methods that were only available in the modified version of Class::MethodMaker v1.08.
provide_legacy_method
Class::IntrospectionMethods provides a set of features that enable you to query the available methods of a class. These methods can be invoked as class methods or object methods. From now on, a class created with Class::IntrospectionMethods will be called a CIMed class.
The top-down introspection is triggered by the global_catalog option.
global_catalog
When set, the global_catalog will invoke the "set_global_catalog" in Class::IntrospectionMethods::Catalog function. This function will use the parameters you passed to the global_catalog option to install a new method in your class. E.g., this global_catalog option:
package Foo::Bar ; use Class::IntrospectionMethods qw/make_methods/; make_methods ( global_catalog => { name => 'metacat', list => [ [qw/foo bar baz/] => foo_cat, [qw/a b z/] => alpha_cat, ], }, )
will enable you to call:
&Foo::Bar::metacat->all_catalog ; # return alpha_cat foo_cat my $obj = Foo::Bar-> new; $obj -> metacat->all_catalog ; # also return alpha_cat foo_cat
See Class::IntrospectionMethods::Catalog for:
The other informations you can retrieve through the global catalog.
How to move a slot from one catalog to another at run-time (only the object catalog can be modified)
The distinction between the class catalog and the object catalog
Note that IntrospectionMethods does not check whether the method declared in global_catalog are actually created by IntrospectionMethods or created elsewhere.
If you use tied scalars (with the tie_scalar or hash method types), or object method type, your tied scalars or objects may need to call the parent CIMed object.
tie_scalar
hash
For instance, if you want to implement error handling in your tied scalar or objects that will call the parent CIMed object or display error messages giving back to the user the slot name containing the faulty object.
So if you need to query the slot name, or index value (for hash or array method types), or be able to call the parent object, you can use the parent option when creating the parent CIMed class:
array
parent
package FOO ; use Class::IntrospectionMethods 'parent' , object => [ foo => 'My::Class' ];
Using this option will graft one attribute and its accessor method. Be default, this attribute and accessor method will be named cim_parent, but this can be changed with set_parent_method_name.
cim_parent
set_parent_method_name
This attribute contains (and the accessor method will return) a Class::IntrospectionMethods::ParentInfo object. This object features methods index_value, slot_name and parent. See "ParentInfo class" in Class::IntrospectionMethods::Parent for more details.
Class::IntrospectionMethods::ParentInfo
index_value
slot_name
CMM_PARENT
Reference of the parent object.
CMM_SLOT_NAME
slot name to use to get the child object from the parent.
CMM_INDEX_VALUE
index value (for tie_tie_hash method type) to use to get the child object from the parent.
tie_tie_hash
When using the -parent option, a CMM_PARENT, CMM_SLOT_NAME and CMM_INDEX_VALUE methods are also grafted to the child's class.
-parent
Here is an example to retrieve a parent object :
package FOO ; use ExtUtils::testlib; '-parent' , object_tie_hash => [ { slot => 'bar', tie_hash => ['MyHash'], class => ['MyObj', 'a' => 'foo'] } ], new => 'new'; package main; my $o = new X; my $obj = $o->a('foo') ; my $p= $obj->metadad->parent; # $p is $o
See "EXAMPLE" in Class::IntrospectionMethods::Parent for further details
Creates a basic constructor.
Takes a single string or a reference to an array of strings as its argument. For each string creates a simple method that creates and returns an object of the appropriate class.
This method may be called as a class method, as usual, or as in instance method, in which case a new object of the same class as the instance will be created.
Creates a basic constructor which calls a method named init after instantiating the object. The init method should be defined in the class using IntrospectionMethods.
init
Takes a single string or a reference to an array of strings as its argument. For each string creates a simple method that creates an object of the appropriate class, calls init on that object propagating all arguments, before returning the object.
Constructor arguments will be stored as a key, value pairs in the object. No check is done regarding the consistencies of the data passed to the constructor and the accessor methods created.
Takes a single string or a reference to an array of strings as its argument. Each string specifies a slot, for which accessor methods are created. E.g.
get_set => 'foo', get_set => [qw/foo bar/],
The accessor methods are, by default:
If an argument is provided, sets a new value for x. This is true even if the argument is undef (cf. no argument, which does not set.)
Returns (new) value.
Value defaults to undef.
Sets value to undef. This is exactly equivalent to
$foo->x (undef)
No return.
This is your basic get/set method, and can be used for slots containing any scalar value, including references to non-scalar data. Note, however, that IntrospectionMethods has meta-methods that define more useful sets of methods for slots containing references to lists, hashes, and objects.
Creates methods for accessing a slot that contains an object of a given class.
object => [ phooey => { class => 'Foo' }, [ qw / bar1 bar2 bar3 / ] => { class => 'Bar'}, foo => { class => 'Baz' constructor_args => [ set => 'it' ]}, [qw/dog fox/] => { class => 'Fob', constructor_args => [ sound => 'bark' ] }, cat => { class => 'Fob', constructor_args => [ sound => 'miaow' ]} tiger => { class => 'Special', init => 'my_init' # method to call after creation } ]
The main argument is an array reference. The array should contain a set of slot_name => hash_ref pairs. slot_name can be an array ref if you want to specify several slots the same way.
slot_name => hash_ref
The hash ref sub-arguments are parsed thus:
The class name of the stored object.
A array ref containing arguments that are passed to the new constructor.
new
Name of a initialisation method to call on the newly created object. The method name defaults to cim_init. In other words if the user class feature a cim_init method, this one will be called after creation of the object.
cim_init
For each slot x, the following methods are created:
x
A get/set method.
If supplied with an object of an appropriate type, will set set the slot to that value.
Else, if the slot has no value, then an object is created by calling new on the appropriate class, passing in any supplied arguments. These arguments may supersede the arguments passed with the constructor_args parameters (See above).
constructor_args
The stored object is then returned.
Will destroy the object held by x.
Will return true if x contains an object. False otherwise.
Create a get/set method to deal with the tied scalar.
Takes a list of pairs, where the first is the name of the slot (or an array ref containing a list of slots), the second is an array reference. The array reference takes the usual tie parameters.
For instance if Enum and Boolean are tied scalar that accept default values, you can have:
tie_scalar => [ foo => [ 'Enum', enum => [qw/A B C/], default => 'B' ], bar => [ 'Enum', enum => [qw/T0 T1/], default => 'T1'], baz => ['Boolean', default => 0], [qw/lots of slots/] => ['Boolean', default => 1], ],
Foreach slot xx, tie_scalar install the following methods:
xx
Return the object tied behind the scalar. Auto-vivify if necessary.
Creates a group of methods for dealing with hash data stored in a slot.
hash => [ 'plain_hash1', 'plain_hash2', [qw/lot of plain hashes/] , yet_another_plain_hash => {} , my_tied_hash => {tied_hash => 'My_Tie_Hash' }, my_tied_hash_with_args => { tied_hash => [ 'My_Tie_Hash' , @my_args ] }, my_hash_with_tied_storage => { tie_storage => 'MyTieScalar' }, [qw/likewise_with_args likewise_with_other_args/] => { tie_storage => [ 'MyTieScalar', @my_args] } my_tied_hash_with_tied_storage => { tied_hash => 'My_Tie_Hash',tie_storage => 'MyTieScalar' }, my_hash_with_object => { class_storage => 'MyClass' }, my_hash_with_object_and_constructor_args => { class_storage => [ 'MyClass' , @my_args ] }, ]
The hash parameters are:
A string or a a reference to an array of strings. For each of these string, a hash based slot is created.
A hash ref who contains attributes attached to the slot(s) defined by the previous arguments. These attribute are used to specify the behavior of the hash attached to the slot or to specialize the hash values. See Tie::Hash::CustomStorage for details on the possibles attributes.
For each slot defined, creates:
Called with no arguments returns the hash stored in the slot, as a hash in a list context or as a reference in a scalar context.
Called with one simple scalar argument it treats the argument as a key and returns the value stored under that key.
Called with more than one argument, treats them as a series of key/value pairs and adds them to the hash.
Returns the keys of the hash.
Returns the list of values.
Takes a single key, returns whether that key exists in the hash.
Takes a list, deletes each key from the hash.
Resets hash to empty.
Creates several methods for dealing with slots containing array data.
array => [ 'plain_array1', 'plain_array2', [qw/lot of plain arrayes/] , yet_another_plain_array => {} , my_tied_array => {tied_array => 'My_Tie_Array' }, my_tied_array_with_args => { tied_array => [ 'My_Tie_Array' , @my_args ] }, my_array_with_tied_storage => { tie_storage => 'MyTieScalar' }, [qw/likewise_with_args likewise_with_other_args/] => { tie_storage => [ 'MyTieScalar', @my_args] } my_tied_array_with_tied_storage => { tied_array => 'My_Tie_Array',tie_storage => 'MyTieScalar' }, my_array_with_object => { class_storage => 'MyClass' }, my_array_with_object_and_constructor_args => { class_storage => [ 'MyClass' , @my_args ] }, ]
The array parameters are:
A string or a a reference to an array of strings. For each of these string, a array based slot is created.
A array ref who contains attributes attached to the slot(s) defined by the previous arguments. These attribute are used to specify the behavior of the array attached to the slot or to specialize the array values. See Tie::Array::CustomStorage for details on the possible attributes.
This method returns the list of values stored in the slot. In an array context it returns them as an array and in a scalar context as a reference to the array. If any arguments are provided to this method, they replace the current list contents.
Returns the number of elements in x.
Takes a list of indices, returns a list of the corresponding values.
Takes a list, treated as pairs of index => value; each given index is set to the corresponding value. No return.
You can simply create an object with Class::IntrospectionMethods using a CIMed class in an object* method. For instance, if you want to create a model of a school clas and their students, you can write:
object*
Package School_class; use Class::IntrospectionMethods get_set => 'grade', hash => [ student => { class_storage => 'Student'} ], new => 'new' ;
And here is the declaration of the Student class that is used in the School_class declararion :
School_class
Package Student ; use Class::IntrospectionMethods get_set => 'age', new => 'new' ;
Now you can use these lines to get and set the student attributes:
my $son_class = School_class->new ; $son_class->grade('first') ; $son_class->student('Ginger')->age(22) ; my $ginger = $son_class->student('Ginger') ; print $ginger->age ;
Email the author.
To Martyn J. Pearce for Class::MethodMaker and the enlightening discussion we had a while ago about parent and catalog.
Class::MethodMaker
To Matthew Simon Cavalletto for the parameter translation idea that I pilfered from Class::MakeMethods.
Class::MakeMethods
Current Maintainer: Dominique Dumont domi@komarr.grenoble.hp.com
Original Authors: Martyn J. Pearce fluffy@cpan.org, Peter Seibel (Organic Online)
Contributions from:
Evolution Online Systems, Inc. http://www.evolution.com Matthew Persico Yitzchak Scott-Thoennes
Copyright (c) 2004 Dominique Dumont. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Copyright (c) 2002, 2001, 2000 Martyn J. Pearce. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Copyright 1998, 1999, 2000 Evolution Online Systems, Inc. You may use this software for free under the terms of the MIT License. More info posted at http://www.evolution.com, or contact info@evolution.com Copyright (c) 1996 Organic Online. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
C<Class::Struct>, C<Class::MakeMethods>, C<Class::MethodMaker>, "Object-Oriented Perl" by Damian Conway. C<Tie::Hash::CustomStorage>, C<Tie::Array::CustomStorage>, C<Class::IntrospectionMethods::Parent>, C<Class::IntrospectionMethods::Catalog>
To install Class::IntrospectionMethods, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Class::IntrospectionMethods
CPAN shell
perl -MCPAN -e shell install Class::IntrospectionMethods
For more information on module installation, please visit the detailed CPAN module installation guide.