in reply to An Object Structural Design Pattern in Perl

my $self = { object=>$object_ref, } unless ref $class;

Per my reading of this code (without running any tests), I believe this will allow you to call the constructor as an instance method and get back the previously-created object--not the same instance, but the most recently created instance.

What did you intend to do here?

Replies are listed 'Best First'.
Re^2: An Object Structural Design Pattern in Perl
by hypochrismutreefuzz (Scribe) on Nov 05, 2007 at 18:08 UTC

    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.

      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);