2 package Class::MOP::Package;
7 use Scalar::Util 'blessed', 'reftype';
9 use Sub::Name 'subname';
11 our $VERSION = '0.92';
12 $VERSION = eval $VERSION;
13 our $AUTHORITY = 'cpan:STEVAN';
15 use base 'Class::MOP::Object';
20 my ( $class, @args ) = @_;
22 unshift @args, "package" if @args % 2;
25 my $package_name = $options{package};
28 # we hand-construct the class
29 # until we can bootstrap it
30 if ( my $meta = Class::MOP::get_metaclass_by_name($package_name) ) {
33 my $meta = ( ref $class || $class )->_new({
34 'package' => $package_name,
38 Class::MOP::store_metaclass_by_name($package_name, $meta);
45 my ( $class, @args ) = @_;
47 unshift @args, "package" if @args % 2;
50 my $package_name = delete $options{package};
52 (defined $package_name && $package_name
53 && (!blessed $package_name || $package_name->isa('Class::MOP::Package')))
54 || confess "You must pass a package name or an existing Class::MOP::Package instance";
56 $package_name = $package_name->name
57 if blessed $package_name;
59 Class::MOP::remove_metaclass_by_name($package_name);
61 $class->initialize($package_name, %options); # call with first arg form for compat
67 return Class::MOP::Class->initialize($class)->new_object(@_)
68 if $class ne __PACKAGE__;
70 my $params = @_ == 1 ? $_[0] : {@_};
73 package => $params->{package},
76 # because of issues with the Perl API
77 # to the typeglob in some versions, we
78 # need to just always grab a new
79 # reference to the hash in the accessor.
80 # Ideally we could just store a ref and
81 # it would Just Work, but oh well :\
91 # all these attribute readers will be bootstrapped
92 # away in the Class::MOP bootstrap section
96 # because of issues with the Perl API
97 # to the typeglob in some versions, we
98 # need to just always grab a new
99 # reference to the hash here. Ideally
100 # we could just store a ref and it would
101 # Just Work, but oh well :\
103 \%{$_[0]->{'package'} . '::'}
116 sub _deconstruct_variable_name {
117 my ($self, $variable) = @_;
120 || confess "You must pass a variable name";
122 my $sigil = substr($variable, 0, 1, '');
125 || confess "The variable name must include a sigil";
127 (exists $SIGIL_MAP{$sigil})
128 || confess "I do not recognize that sigil '$sigil'";
130 return ($variable, $sigil, $SIGIL_MAP{$sigil});
136 # ... these functions have to touch the symbol table itself,.. yuk
138 sub add_package_symbol {
139 my ($self, $variable, $initial_value) = @_;
141 my ($name, $sigil, $type) = ref $variable eq 'HASH'
142 ? @{$variable}{qw[name sigil type]}
143 : $self->_deconstruct_variable_name($variable);
145 my $pkg = $self->{'package'};
148 no warnings 'redefine', 'misc', 'prototype';
149 *{$pkg . '::' . $name} = ref $initial_value ? $initial_value : \$initial_value;
152 sub remove_package_glob {
153 my ($self, $name) = @_;
155 delete ${$self->name . '::'}{$name};
158 # ... these functions deal with stuff on the namespace level
160 sub has_package_symbol {
161 my ( $self, $variable ) = @_;
163 my ( $name, $sigil, $type )
164 = ref $variable eq 'HASH'
165 ? @{$variable}{qw[name sigil type]}
166 : $self->_deconstruct_variable_name($variable);
168 my $namespace = $self->namespace;
170 return 0 unless exists $namespace->{$name};
172 my $entry_ref = \$namespace->{$name};
173 if ( reftype($entry_ref) eq 'GLOB' ) {
174 if ( $type eq 'SCALAR' ) {
175 return defined( ${ *{$entry_ref}{SCALAR} } );
178 return defined( *{$entry_ref}{$type} );
183 # a symbol table entry can be -1 (stub), string (stub with prototype),
184 # or reference (constant)
185 return $type eq 'CODE';
189 sub get_package_symbol {
190 my ($self, $variable) = @_;
192 my ($name, $sigil, $type) = ref $variable eq 'HASH'
193 ? @{$variable}{qw[name sigil type]}
194 : $self->_deconstruct_variable_name($variable);
196 my $namespace = $self->namespace;
199 $self->add_package_symbol($variable)
200 unless exists $namespace->{$name};
202 my $entry_ref = \$namespace->{$name};
204 if ( ref($entry_ref) eq 'GLOB' ) {
205 return *{$entry_ref}{$type};
208 if ( $type eq 'CODE' ) {
210 return \&{ $self->name . '::' . $name };
218 sub remove_package_symbol {
219 my ($self, $variable) = @_;
221 my ($name, $sigil, $type) = ref $variable eq 'HASH'
222 ? @{$variable}{qw[name sigil type]}
223 : $self->_deconstruct_variable_name($variable);
226 # no doubt this is grossly inefficient and
227 # could be done much easier and faster in XS
229 my ($scalar_desc, $array_desc, $hash_desc, $code_desc) = (
230 { sigil => '$', type => 'SCALAR', name => $name },
231 { sigil => '@', type => 'ARRAY', name => $name },
232 { sigil => '%', type => 'HASH', name => $name },
233 { sigil => '&', type => 'CODE', name => $name },
236 my ($scalar, $array, $hash, $code);
237 if ($type eq 'SCALAR') {
238 $array = $self->get_package_symbol($array_desc) if $self->has_package_symbol($array_desc);
239 $hash = $self->get_package_symbol($hash_desc) if $self->has_package_symbol($hash_desc);
240 $code = $self->get_package_symbol($code_desc) if $self->has_package_symbol($code_desc);
242 elsif ($type eq 'ARRAY') {
243 $scalar = $self->get_package_symbol($scalar_desc) if $self->has_package_symbol($scalar_desc);
244 $hash = $self->get_package_symbol($hash_desc) if $self->has_package_symbol($hash_desc);
245 $code = $self->get_package_symbol($code_desc) if $self->has_package_symbol($code_desc);
247 elsif ($type eq 'HASH') {
248 $scalar = $self->get_package_symbol($scalar_desc) if $self->has_package_symbol($scalar_desc);
249 $array = $self->get_package_symbol($array_desc) if $self->has_package_symbol($array_desc);
250 $code = $self->get_package_symbol($code_desc) if $self->has_package_symbol($code_desc);
252 elsif ($type eq 'CODE') {
253 $scalar = $self->get_package_symbol($scalar_desc) if $self->has_package_symbol($scalar_desc);
254 $array = $self->get_package_symbol($array_desc) if $self->has_package_symbol($array_desc);
255 $hash = $self->get_package_symbol($hash_desc) if $self->has_package_symbol($hash_desc);
258 confess "This should never ever ever happen";
261 $self->remove_package_glob($name);
263 $self->add_package_symbol($scalar_desc => $scalar) if defined $scalar;
264 $self->add_package_symbol($array_desc => $array) if defined $array;
265 $self->add_package_symbol($hash_desc => $hash) if defined $hash;
266 $self->add_package_symbol($code_desc => $code) if defined $code;
269 sub list_all_package_symbols {
270 my ($self, $type_filter) = @_;
272 my $namespace = $self->namespace;
273 return keys %{$namespace} unless defined $type_filter;
276 # or we can filter based on
277 # type (SCALAR|ARRAY|HASH|CODE)
278 if ( $type_filter eq 'CODE' ) {
280 (ref($namespace->{$_})
281 ? (ref($namespace->{$_}) eq 'SCALAR')
282 : (ref(\$namespace->{$_}) eq 'GLOB'
283 && defined(*{$namespace->{$_}}{CODE})));
284 } keys %{$namespace};
286 return grep { *{$namespace->{$_}}{$type_filter} } keys %{$namespace};
292 sub wrap_method_body {
293 my ( $self, %args ) = @_;
295 ('CODE' eq ref $args{body})
296 || confess "Your code block must be a CODE reference";
298 $self->method_metaclass->wrap(
299 package_name => $self->name,
305 my ($self, $method_name, $method) = @_;
306 (defined $method_name && $method_name)
307 || confess "You must define a method name";
310 if (blessed($method)) {
311 $body = $method->body;
312 if ($method->package_name ne $self->name) {
313 $method = $method->clone(
314 package_name => $self->name,
316 ) if $method->can('clone');
319 $method->attach_to_class($self);
320 $self->_method_map->{$method_name} = $method;
323 # If a raw code reference is supplied, its method object is not created.
324 # The method object won't be created until required.
329 my ( $current_package, $current_name ) = Class::MOP::get_code_info($body);
331 if ( !defined $current_name || $current_name eq '__ANON__' ) {
332 my $full_method_name = ($self->name . '::' . $method_name);
333 subname($full_method_name => $body);
336 $self->add_package_symbol(
337 { sigil => '&', type => 'CODE', name => $method_name },
343 my ( $self, $code ) = @_;
345 my ( $code_package, $code_name ) = Class::MOP::get_code_info($code);
347 return $code_package && $code_package eq $self->name
348 || ( $code_package eq 'constant' && $code_name eq '__ANON__' );
352 my ($self, $method_name) = @_;
353 (defined $method_name && $method_name)
354 || confess "You must define a method name";
356 return defined($self->get_method($method_name));
360 my ($self, $method_name) = @_;
361 (defined $method_name && $method_name)
362 || confess "You must define a method name";
364 my $method_map = $self->_method_map;
365 my $method_object = $method_map->{$method_name};
366 my $code = $self->get_package_symbol({
367 name => $method_name,
372 unless ( $method_object && $method_object->body == ( $code || 0 ) ) {
373 if ( $code && $self->_code_is_mine($code) ) {
374 $method_object = $method_map->{$method_name}
375 = $self->wrap_method_body(
377 name => $method_name,
378 associated_metaclass => $self,
382 delete $method_map->{$method_name};
387 return $method_object;
391 my ($self, $method_name) = @_;
392 (defined $method_name && $method_name)
393 || confess "You must define a method name";
395 my $removed_method = delete $self->get_method_map->{$method_name};
397 $self->remove_package_symbol(
398 { sigil => '&', type => 'CODE', name => $method_name }
401 $removed_method->detach_from_class if $removed_method;
403 $self->update_package_cache_flag; # still valid, since we just removed the method from the map
405 return $removed_method;
408 sub get_method_list {
410 return grep { $self->has_method($_) } keys %{ $self->namespace };
421 Class::MOP::Package - Package Meta Object
425 The Package Protocol provides an abstraction of a Perl 5 package. A
426 package is basically namespace, and this module provides methods for
427 looking at and changing that namespace's symbol table.
433 =item B<< Class::MOP::Package->initialize($package_name) >>
435 This method creates a new C<Class::MOP::Package> instance which
436 represents specified package. If an existing metaclass object exists
437 for the package, that will be returned instead.
439 =item B<< Class::MOP::Package->reinitialize($package) >>
441 This method forcibly removes any existing metaclass for the package
442 before calling C<initialize>. In contrast to C<initialize>, you may
443 also pass an existing C<Class::MOP::Package> instance instead of just
444 a package name as C<$package>.
446 Do not call this unless you know what you are doing.
448 =item B<< $metapackage->name >>
450 This is returns the package's name, as passed to the constructor.
452 =item B<< $metapackage->namespace >>
454 This returns a hash reference to the package's symbol table. The keys
455 are symbol names and the values are typeglob references.
457 =item B<< $metapackage->add_package_symbol($variable_name, $initial_value) >>
459 This method accepts a variable name and an optional initial value. The
460 C<$variable_name> must contain a leading sigil.
462 This method creates the variable in the package's symbol table, and
463 sets it to the initial value if one was provided.
465 =item B<< $metapackage->get_package_symbol($variable_name) >>
467 Given a variable name, this method returns the variable as a reference
468 or undef if it does not exist. The C<$variable_name> must contain a
471 =item B<< $metapackage->has_package_symbol($variable_name) >>
473 Returns true if there is a package variable defined for
474 C<$variable_name>. The C<$variable_name> must contain a leading sigil.
476 =item B<< $metapackage->remove_package_symbol($variable_name) >>
478 This will remove the package variable specified C<$variable_name>. The
479 C<$variable_name> must contain a leading sigil.
481 =item B<< $metapackage->remove_package_glob($glob_name) >>
483 Given the name of a glob, this will remove that glob from the
484 package's symbol table. Glob names do not include a sigil. Removing
485 the glob removes all variables and subroutines with the specified
488 =item B<< $metapackage->list_all_package_symbols($type_filter) >>
490 This will list all the glob names associated with the current
491 package. These names do not have leading sigils.
493 You can provide an optional type filter, which should be one of
494 'SCALAR', 'ARRAY', 'HASH', or 'CODE'.
496 =item B<< $metapackage->get_all_package_symbols($type_filter) >>
498 This works much like C<list_all_package_symbols>, but it returns a
499 hash reference. The keys are glob names and the values are references
500 to the value for that name.
504 =head2 Method introspection and creation
506 These methods allow you to introspect a class's methods, as well as
507 add, remove, or change methods.
509 Determining what is truly a method in a Perl 5 class requires some
510 heuristics (aka guessing).
512 Methods defined outside the package with a fully qualified name (C<sub
513 Package::name { ... }>) will be included. Similarly, methods named
514 with a fully qualified name using L<Sub::Name> are also included.
516 However, we attempt to ignore imported functions.
518 Ultimately, we are using heuristics to determine what truly is a
519 method in a class, and these heuristics may get the wrong answer in
520 some edge cases. However, for most "normal" cases the heuristics work
525 =item B<< $metapackage->get_method($method_name) >>
527 This will return a L<Class::MOP::Method> for the specified
528 C<$method_name>. If the class does not have the specified method, it
531 =item B<< $metapackage->has_method($method_name) >>
533 Returns a boolean indicating whether or not the class defines the
534 named method. It does not include methods inherited from parent
537 =item B<< $metapackage->get_method_map >>
539 Returns a hash reference representing the methods defined in this
540 class. The keys are method names and the values are
541 L<Class::MOP::Method> objects.
543 =item B<< $metapackage->get_method_list >>
545 This will return a list of method I<names> for all methods defined in
548 =item B<< $metapackage->add_method($method_name, $method) >>
550 This method takes a method name and a subroutine reference, and adds
551 the method to the class.
553 The subroutine reference can be a L<Class::MOP::Method>, and you are
554 strongly encouraged to pass a meta method object instead of a code
555 reference. If you do so, that object gets stored as part of the
556 class's method map directly. If not, the meta information will have to
557 be recreated later, and may be incorrect.
559 If you provide a method object, this method will clone that object if
560 the object's package name does not match the class name. This lets us
561 track the original source of any methods added from other classes
562 (notably Moose roles).
564 =item B<< $metapackage->remove_method($method_name) >>
566 Remove the named method from the class. This method returns the
567 L<Class::MOP::Method> object for the method.
569 =item B<< $metapackage->method_metaclass >>
571 Returns the class name of the method metaclass, see
572 L<Class::MOP::Method> for more information on the method metaclass.
574 =item B<< $metapackage->wrapped_method_metaclass >>
576 Returns the class name of the wrapped method metaclass, see
577 L<Class::MOP::Method::Wrapped> for more information on the wrapped
580 =item B<< Class::MOP::Package->meta >>
582 This will return a L<Class::MOP::Class> instance for this class.
588 Stevan Little E<lt>stevan@iinteractive.comE<gt>
590 =head1 COPYRIGHT AND LICENSE
592 Copyright 2006-2009 by Infinity Interactive, Inc.
594 L<http://www.iinteractive.com>
596 This library is free software; you can redistribute it and/or modify
597 it under the same terms as Perl itself.