From: Jarkko Hietaniemi Date: Mon, 10 Sep 2001 12:46:34 +0000 (+0000) Subject: Further Class::Struct patching from Damian. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=5551626dc585a9fdfe1494be006dd6c01306fbac;p=p5sagit%2Fp5-mst-13.2.git Further Class::Struct patching from Damian. The new new semantics are: * If you pass an initializer for a nested object, it has to be: a) a reference to an object of that class, or b) a reference to an object of a subclass of that class, or c) a reference to a hash of arguments to be passed to the class's constructor * If you pass no initializer for a nested object, the attribute is initialized to C p4raw-id: //depot/perl@11976 --- diff --git a/lib/Class/Struct.pm b/lib/Class/Struct.pm index 4685bd1..a3d235c 100644 --- a/lib/Class/Struct.pm +++ b/lib/Class/Struct.pm @@ -163,10 +163,13 @@ sub struct { $out .= " \$r->$elem = $init undef;$cmt\n"; } elsif( $type =~ /^\w+(?:::\w+)*$/ ){ - $init = "defined(\$init{'$name'}) ? \$init{'$name'} : undef"; - $out .= " croak 'Initializer for $name must be $type reference'\n"; - $out .= " if defined(\$init{'$name'}) && !UNIVERSAL::isa(\$init{'$name'}, '$type');\n"; - $out .= " \$r->$elem = $init;$cmt\n"; + $out .= " if (defined(\$init{'$name'})) {\n"; + $out .= " if (ref \$init{'$name'} eq 'HASH')\n"; + $out .= " { \$r->$elem = $type->new(\%{\$init{'$name'}}) } $cmt\n"; + $out .= " elsif (UNIVERSAL::isa(\$init{'$name'}, '$type'))\n"; + $out .= " { \$r->$elem = \$init{'$name'} } $cmt\n"; + $out .= " else { croak 'Initializer for $name must be hash or $type reference' }\n"; + $out .= " }\n"; $classes{$name} = $type; $got_class = 1; } @@ -416,8 +419,8 @@ The object reference is returned. =item Class (C<'Class_Name'> or C<'*Class_Name'>) The element's value must be a reference blessed to the named -class or to one of its subclasses. The element is initialized to -the result of calling the C constructor of the named class. +class or to one of its subclasses. The element is not initialized +by default. The accessor's argument, if any, is assigned to the element. The accessor will C if this is not an appropriate object @@ -441,7 +444,8 @@ initializer for an array element is an array reference. The initializer for a hash is a hash reference. The initializer for a class element is an object of the corresponding class, -(or of one of its subclasses). +or of one of it's subclasses, or a reference to a hash containing named +arguments to be passed to the element's constructor. See Example 3 below for an example of initialization. @@ -521,9 +525,9 @@ If no initializer is specified for a particular element, its default initialization is performed instead. Initializers for non-existent elements are silently ignored. -Note that the initializer for a nested struct is specified -as an anonymous hash of initializers, which is passed on to the nested -struct's constructor. +Note that the initializer for a nested class may be specified as +an object of that class, or as a reference to a hash of initializers +that are passed on to the nested struct's constructor. use Class::Struct; @@ -546,6 +550,7 @@ struct's constructor. kittens => ['Monica', 'Kenneth'], markings => { socks=>1, blaze=>"white" }, breed => Breed->new(name=>'short-hair', cross=>1), + or: breed => {name=>'short-hair', cross=>1}, ); print "Once a cat called ", $cat->name, "\n"; @@ -556,17 +561,19 @@ struct's constructor. =head1 Author and Modification History -Modified by Damian Conway, 2001-09-04, v0.61. +Modified by Damian Conway, 2001-09-10, v0.62. - Removed implicit construction of nested objects. - This helpfulness was fraught with problems: + Modified implicit construction of nested objects. + Now will also take an object ref instead of requiring a hash ref. + Also default initializes nested object attributes to undef, rather + than calling object constructor without args + Original over-helpfulness was fraught with problems: * the class's constructor might not be called 'new' + * the class might not have a hash-like-arguments constructor * the class might not have a no-argument constructor - * "recursive" data structures don't work well: + * "recursive" data structures didn't work well: package Person; struct { mother => 'Person', father => 'Person'}; - It is now necessary to pass an object reference to initialize a - nested object. Modified by Casey West, 2000-11-08, v0.59.