in reply to Re: An Object Structural Design Pattern in Perl
in thread An Object Structural Design Pattern in Perl

The "unless" is used to prevent calling the constructor as an instance method. The constructor can ONLY be called on the class name. Thus

CGI::Armature::Storage->new($obj, $hash);

will work while

$obj->new($obj, $hash);

will cause a fatal error due to $self not being initialized.

edit: Dec 10 2007

Sorry about that. I will append an edited version of my code after this reply.

Replies are listed 'Best First'.
Re^3: An Object Structural Design Pattern in Perl
by chromatic (Archbishop) on Nov 06, 2007 at 02:32 UTC

    How is it a fatal error? It's effectively a semi-static variable, but I don't see any error checking code.

    I would have expected something like croak( 'Cannot call constructor on instance' ) if blessed( $class );, but all I see is mixing a lexical declaration with a postfix conditional, which usually isn't the right thing.

      I feel embarrased to admit that I hadn't tested the code myself. After testing and debugging I decided to simplify the design and change the way the method calls are dispatched.
      package Bridge::Simple; use strict; sub new { my $class = shift; my $object_ref = shift; my $method_map = shift; my $self = {}; $self->{$_} = $method_map->{$_} for keys %$method_map; $self->{object} = $object_ref; return bless($self, $class); } sub AUTOLOAD { my $self = shift; use vars '$AUTOLOAD'; $AUTOLOAD =~ s/.*:://; my $method = $self->{$AUTOLOAD}; return $self->{object}->$method(@_); } 1;
      use Bridge::Simple; use XML::Simple; my $serialize_map = { serialize=>'XMLin', deserialize=>'XMLout', }; my $serializer = Bridge::Simple->new( XML::Simple->new( suppressempty=>q{}, noattr=>1 ), $serialize_map, );

      This snippet of client code instantiates a Serializer object with a method_map that maps "serialize" with "XMLout" and "deserialize" with "XMLin" using the options given to override the default options of XML::Simple.

      use Bridge::Simple; use YAML; my $serialize_map = { serialize=>'Dump', deserialize=>'Load', }; my $serializer = Bridge::Simple->new( YAML->new(), $serialize_map, );

      This snippet of client code does the same thing using YAML as the serialization interface.

      Client code for either serializer object would be identical.

      $data = $serializer->serialize($data_hash); $data_hash = $serializer->deserialize($data);