0
###############################################################################
# Attributes
###############################################################################
has 'primary_cluster' => (
    is  => 'ro',
    isa => 'Str',
    required => TRUE,
);

has 'secondary_cluster' => (
    is  => 'ro',
    isa => 'Str',
    required => FALSE,
    default => sub {$_[0]->primary_cluster},
);

has '_connection' => (
    is => 'ro',
    required => FALSE,
    init_arg => undef,
    default => sub {
        Core::mConnection->new(
            primary_cluster => $_[0]->primary_cluster,
            secondary_cluster => $_[0]->secondary_cluster,
        );
    },
);

I'm trying to have a private attribute _connection that uses other attributes to create a mConnection object. The problem I'm running into is that inside the default subroutine of _connection, $_[0]->primary_cluster is always undef. Is there any way to guarantee order to the attribute creation or is there a better way to go about doing this?

I do not want this attribute to be lazy; I need it to be created when the object is constructed.

ikegami
  • 367,544
  • 15
  • 269
  • 518
Takkun
  • 6,131
  • 16
  • 52
  • 69

1 Answers1

3

The object is still being constructed! Delay your attribute's initialization until after it's constructed. the following delays its initialization until it's used:

lazy => 1

You could also use a BUILD method instead of a default.

sub BUILD {
   my $self = shift;

   $self->_connection(
      Core::mConnection->new(
         primary_cluster   => $self->primary_cluster,
         secondary_cluster => $self->secondary_cluster,
      )
   );
}

Of course, you'll need to make the attribute writable first.

ikegami
  • 367,544
  • 15
  • 269
  • 518