Change 11976 by jhi@alpha on 2001/09/10 12:46:34

        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<undef>

Affected files ...

... //depot/perl/lib/Class/Struct.pm#22 edit

Differences ...

==== //depot/perl/lib/Class/Struct.pm#22 (text) ====
Index: perl/lib/Class/Struct.pm
--- perl/lib/Class/Struct.pm.~1~        Mon Sep 10 07:00:06 2001
+++ perl/lib/Class/Struct.pm    Mon Sep 10 07:00:06 2001
@@ -163,10 +163,13 @@
             $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 @@
 =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<new> 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<croak> if this is not an appropriate object
@@ -441,7 +444,8 @@
 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 @@
 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 @@
                         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 @@
 
 =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.
End of Patch.

Reply via email to