1 # This module is part of DA, Don Armstrong's Modules, and is released
2 # under the terms of the GPL version 2, or any later version. See the
3 # file README and COPYING for more information. Copyright 2003 by Don
4 # Armstrong <don@donarmstrong.com>.
7 package Class::Modular;
11 Class::Modular -- Modular class generation superclass
17 use base qw(Class::Modular);
22 Class::Modular is a superclass for generating modular classes, where
23 methods can be added into the class from the perspective of the
24 object, rather than the perspective of the class.
26 That is, you can create a class which has a set of generic common
27 functions. Less generic functions can be included or overridden
28 without modifying the base classes. This allows for code to be more
29 modular, and reduces code duplication.
36 use vars qw($VERSION $DEBUG $REVISION);
40 use Storable qw(dclone); # Used for deep copying objects
44 ($REVISION) = q$LastChangedRevision$ =~ /\$LastChangedRevision:\s+([^\s+])/;
45 $DEBUG = 0 unless defined $DEBUG;
53 Usage : $obj = Foo::Bar->new();
54 Function: Creates a new Foo::Bar object
55 Returns : A new Foo::Bar object
58 Aditional arguments can be passed to this creator, and they are
59 stored in $self->{_creation_args}. You can also override the new
60 method in your subclass. It's just provided here for completeness.
65 my ($class,@args) = @_;
67 # We shouldn't be called $me->new, but just in case
68 $class = ref($class) || $class;
87 Stores the arguments used at new so modules that are loaded later can
93 my ($self,@creation_args) = @_;
95 $self->{creation_args} = [@_];
102 Usage : $db->load('FOO::Subclass');
103 Function: loads a Class::Modular subclass
105 Args : SCALAR subclass SCALAR options
107 Loads the named subclass into this object if the named subclass has
110 The options scalar is passed to $subclass::_methods when determining
111 which methods should be added using _addmethods.
113 The subclasses _init method is called right after methods are loaded.
115 If debugging is enabled, will warn about loading already loaded
122 my ($self,$subclass,$options) = @_;
126 # check to see if the subclass has already been loaded.
128 if (not defined $self->{_subclasses}->{$subclass}){
131 eval "require $subclass" or die $@;
132 $self->_addmethods($subclass,&{"${subclass}::_methods"}($self,$options));
133 &{"${subclass}::_init"}($self);
136 $self->{_subclasses}->{$subclass} = {};
139 carp "Not reloading subclass $subclass" if $DEBUG;
146 Usage : $self->_addmethods()
147 Function: Adds the passed methods into the function table
149 Args : ARRAY of methods
151 Given an array of methods, adds the methods into the _methodhash
154 Methods that have previously been overridden by override are _NOT_
155 overridden again. This may need to be adjusted in load.
159 sub _addmethods($@) {
160 my ($self,$subclass,@methods) = @_;
162 # stick the method into the table
163 # DLA: Make with the munchies!
165 foreach my $method (@methods) {
166 if (not $method =~ /^$subclass/) {
167 $method = $subclass.'::'.$method;
169 my ($method_name) = $method =~ /\:*([^\:]+)\s*$/;
170 if (exists $self->{_methodhash}->{$method_name}) {
171 if ($self->{_methodhash}->{$method_name}->{overridden}) {
172 carp "Not overriding already overriden method $method_name\n" if $DEBUG;
175 carp "Overriding $method_name $self->{_methodhash}->{$method_name}->{reference} with $method\n";
177 $self->{_methodhash}->{$method_name}->{reference} = $method;
178 $self->{_methodhash}->{$method_name}->{subclass} = $subclass;
186 Usage : $obj->override('methodname', $code_ref)
187 Function: Overrides the method methodname and calls $code_ref instead.
188 Returns : TRUE on success, FALSE on failure.
189 Args : SCALAR method name
190 CODEREF function reference
192 Allows you to override utility functions that are called internally
193 to provide a different default function.
195 It's superficially similar to _addmethods, which is called by load,
196 but it deals with code references, and requires the method name to be
199 Methods overridden here are _NOT_ overrideable in _addmethods. This
200 may need to be changed.
205 my ($self, $method_name, $function_reference) = @_;
207 $self->{_methodhash}->{$method_name}->{reference} = $function_reference;
208 $self->{_methodhash}->{$method_name}->{overridden} = 1;
214 Usage : my $clone = $obj->clone
215 Function: Produces a clone of the Class::Modular object
219 Produces a clone of the object with duplicates of all data and/or new
220 connections as appropriate.
222 Calls _clone on all loaded subclasses.
224 Warns if debugging is on for classes which don't have a _clone
225 method. Dies on other errors.
233 bless $clone, ref($self);
235 # copy data structures at this level
236 $clone->{_methodhash} = dclone($self->{_methodhash});
237 $clone->{_subclasses} = dclone($self->{_subclasses});
239 foreach my $subclass (keys %{$self->{_subclasses}}) {
240 # use eval to try and call the subclasses _clone method.
241 # Ignore no such function errors, but trap other types of
244 # XXX Switch to can instead.
247 &$subclass::_clone($self,$clone);
250 # Die unless we've hit an undefined subroutine.
251 die $@ unless $@ =~ /Undefined\s*subroutine\s*\&.*\:\:\_clone/;
252 warn "$subclass doesn't have a _clone method\n$@" if $DEBUG;
264 Class::Modular->can('METHOD');
268 Replaces UNIVERSAL's can method so that handled methods are reported
269 correctly. Calls UNIVERSAL::can in the places where we don't know
274 A coderef to the method if the method is supported, undef otherwise.
283 my ($self,$method,$vars) = @_;
285 if (ref $self and exists $self->{_methodhash}->{$method}) {
286 # If the method is defined, return a reference to the
288 return $self->{_methodhash}->{$method}->{reference};
291 # Otherwise, let UNIVERSAL::can deal with the method
293 return UNIVERSAL::can($self,$method);
301 $obj->handledby('methodname');
302 $obj->handledby('Class::Method::methodname');
306 Returns the subclass that handles this method.
319 my ($self,$method_name) = @_;
321 $method_name =~ s/.*\://;
323 if (exists $self->{_methodhash}->{$method_name}) {
324 return $self->{_methodhash}->{$method_name}->{subclass};
338 Calls all subclass _destroy methods.
340 Subclasses need only implement a _destroy method if they have
341 references that need to be uncircularized, or things that should be
342 disconnected or closed.
348 foreach my $subclass (keys %{$self->{_subclasses}}) {
349 # use eval to try and call the subclasses _destroy method.
350 # Ignore no such function errors, but trap other types of
354 &$subclass::_destroy($self);
357 # Die unless we've hit an undefined subroutine.
358 die $@ unless $@ =~ /Undefined\s*subroutine\s*\&.*\:\:\_clone/;
359 warn "$subclass doesn't have a _clone method\n$@" if $DEBUG;
368 Usage : Called by perl
369 Function: Calls child methods which have been installed into this handle
373 The AUTOLOAD function is responsible for calling child methods which
374 have been installed into the current Class::Modular handle.
376 Subclasses that have a new function as well as an AUTOLOAD function
377 must call Class::Modular::AUTOLOAD and set $Class::Modular::AUTOLOAD
379 $Class::Modular::AUTOLOAD = $AUTOLOAD;
380 goto &Class::Modular::AUTOLOAD;
385 my $method = $AUTOLOAD;
391 if (not ref($self)) {
392 carp "Not a reference in AUTOLOAD.";
396 if (exists $self->{_methodhash}->{$method} and
397 defined $self->{_methodhash}->{$method}->{reference}) {
400 goto &{$self->{_methodhash}{$method}{reference}};
404 croak "Undefined function $AUTOLOAD";