File Coverage

blib/lib/Class/Maker/Basic/Constructor.pm
Criterion Covered Total %
statement 15 67 22.3
branch 0 24 0.0
condition 0 8 0.0
subroutine 5 9 55.5
pod 0 2 0.0
total 20 110 18.1


line stmt bran cond sub pod time code
1             #
2             # Author: Murat Uenalan (muenalan@cpan.org)
3             #
4             # Copyright: Copyright (c) 1997 Murat Uenalan. All rights reserved.
5             #
6             # Note: This program is free software; you can redistribute it and/or modify it
7             #
8             # under the same terms as Perl itself.
9            
10             package Class::Maker::Basic::Constructor;
11            
12 1     1   6 require 5.005_62; use strict; use warnings;
  1     1   2  
  1         37  
  1         5  
  1         1  
  1         28  
13            
14 1     1   5 use Exporter;
  1         2  
  1         505  
15            
16             our $VERSION = '0.02';
17            
18             our @ISA = qw(Exporter);
19            
20             our %EXPORT_TAGS = ( 'all' => [ qw(new) ], 'std' => [ qw(new) ] );
21            
22             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
23            
24             our @EXPORT = qw();
25            
26             # Preloaded methods go here.
27            
28             our @init_methods = qw( init initialize );
29            
30             sub simple_new
31             {
32 0     0 0   my $this = shift;
33            
34 0   0       bless {}, ref( $this ) || $this;
35             }
36            
37             =pod
38            
39             "overriden attribute-names" are not dramatic, because every attribute
40             gets its classname prepended like "Object::attribute" into the hash
41             representation of the object.
42            
43             But you must be aware that when initializing via new( public => ),
44             alwas the first parent attribute is used for the initalization.
45            
46             new( Parent1::field => 'bla', Parent2::field => 'blabla' );
47            
48             =cut
49            
50             # multiple inheritance constructor (shouldn't be overriden, otherwise no MI)
51            
52             sub new
53             {
54 0     0 0   my $what = shift;
55            
56 0   0       my $class = ref( $what ) || $what;
57            
58             # convert constructor arguments to accessor/method calls
59            
60 0           my %args = @_;
61            
62 0           my $args = \%args;
63            
64 0           _filter_argnames( $args );
65            
66             # look if we just need cloning
67            
68 0 0         if( ref( $what ) )
69             {
70 0           my %copy = %$what;
71            
72 0           my $clone = bless \%copy, $class;
73            
74 0           while( my ( $key, $value ) = each %args )
75             {
76 0           $clone->$key( $value );
77             }
78            
79 0           return $clone;
80             }
81            
82             # if we do not clone, construct a new instance
83            
84 0           my $this = bless {}, $class;
85            
86             # preset all defaults
87            
88 0 0         my $rfx = Class::Maker::Reflection::reflect( $class ) or die;
89            
90 0 0         if( $rfx->definition )
91             {
92 0 0         _defaults( $this, $rfx->definition->{default} ) if exists $rfx->definition->{default};
93             }
94            
95             # inheriting attributes here
96            
97 0 0         warn( sprintf "NEW TRAVERSING ISA: %s", join( ', ', @{ Class::Maker::Reflection::inheritance_isa( ref( $this ) ) } ) ) if $Class::Maker::DEBUG;
  0            
98            
99 0   0       foreach my $parent ( @{ Class::Maker::Reflection::inheritance_isa( ref( $this ) || die ) } )
  0            
100             {
101 0           my $class = ref($this);
102            
103 0           bless $this, $parent;
104            
105 1     1   5 no strict 'refs';
  1         1  
  1         452  
106            
107 0 0         "${parent}::_preinit"->( $this, $args ) if defined *{ "${parent}::_preinit" }{CODE};
  0            
108            
109 0           foreach my $init_method ( @init_methods )
110             {
111 0 0         if( defined *{ "${parent}::${init_method}" }{CODE} )
  0            
112             {
113 0           "${parent}::${init_method}"->( $this, $args );
114            
115 0           last;
116             }
117             }
118            
119 0           foreach my $attr ( keys %{$args} )
  0            
120             {
121 0 0         if( defined *{ "${parent}::${attr}" }{CODE} )
  0            
122             {
123 0           "${parent}::${attr}"->( $this, $args->{$attr} );
124            
125 0           delete $args->{$attr};
126             }
127             }
128            
129 0 0         "${parent}::_postinit"->( $this, $args ) if defined *{ "${parent}::_postinit" }{CODE};
  0            
130            
131 0           bless $this, $class;
132             }
133            
134             # call constructor arguments as functions, because we assume attribute-handlers
135            
136 0           warn "Unhandled new() arg: '$_' (Implement attribute-handler or check spelling)" for keys %args;
137            
138 0           return $this;
139             }
140            
141             # functions
142            
143             sub _filter_argnames
144             {
145 0     0     my $temp = shift;
146            
147             # rename all -arg or --arg fields
148            
149 0           foreach my $key ( keys %$temp )
150             {
151 0 0         if( $key =~ /^\-+(.*)/ )
152             {
153 0           $temp->{$1} = $temp->{$key};
154            
155 0           delete $temp->{$key};
156             }
157             }
158             }
159            
160             sub _defaults
161             {
162 0     0     my $this = shift;
163            
164 0           my $args = shift;
165            
166 1     1   6 no strict 'refs';
  1         2  
  1         137  
167            
168 0           foreach my $attr ( keys %$args )
169             {
170 0 0         if( my $coderef = $this->can( $attr ) )
171             {
172 0 0         print "Setting $this default (via coderef $coderef) $attr = ", $args->{$attr}, "\n" if $Class::Maker::DEBUG;
173            
174 0           $coderef->( $this, $args->{$attr} );
175            
176             #$this->$attr( $args->{$attr} );
177             #$this->{$attr} = $args->{$attr};
178             }
179             }
180             }
181            
182             1;
183            
184             __END__