xenoterracide
xenoterracide

Reputation: 16857

make object instance immutable

I want to be able to instantiate a Moose based object add to it until I serialize it and then I want to make it unchangeable. How can/should I go about doing this?

Upvotes: 3

Views: 369

Answers (2)

Piers Cawley
Piers Cawley

Reputation: 684

I would make two classes and a common Role:

package Thing
use Moose::Role;

has some_attrib => (isa => 'AnotherThing');

### Behaviour (the important stuff) goes here

package ImmutableThing;
use Moose;

with 'Thing';

has +some_attrib => (is => 'ro');

sub finalize { shift }

package MutableThing
use Moose;

with 'Thing';

has +some_attrib => (is => 'rw');

sub finalize {
    my $self = shift;
    Thing->new({some_attrib => $self->some_attrib});
}

I'm not sure that having mutable and immutable forms of the same class is necessarily a good idea though. I tend to try and think about build time and operation time as two distinct phases with different interfaces.

I would be more inclined to write a Parameter Collector (I've capitalised it like it's a pattern, but I've not seen it in the literature) that has an interface optimised to gathering the info needed to create a Thing, and the Thing Itself, which is the object that's used by the rest of the program.

Upvotes: 1

Richard Huxton
Richard Huxton

Reputation: 22893

I don't know of (and can't easily find) any modules to do this on CPAN which is surprising but explains why you are asking :-)

A "before" modifier over all your attributes is the obvious way to go about it. I'm sure there's a suitable meta-programming way to get a list of all attribute accessors and apply the modifier, but I'd be tempted to explicitly list them all with a big comment.

Have you considered whether you have one class or two here (Thingy, LockedThingy)? Two classes would let you encapsulate the meta cleverness if you're that way inclined.

Upvotes: 0

Related Questions