Home > Net >  How can a attribute (which is a class) access the class to which it is an attribute?
How can a attribute (which is a class) access the class to which it is an attribute?

Time:08-10

A confusing title, I know. But the code should be clear:

class A {
    has $.foo = 1;
    # how can I access B::bar from here?
}

class B {
    has $.bar = 2;
    has A $.a;
    submethod TWEAK {
        $!a = A.new;
    }
}

my $b = B.new;
say $b;    # B.new(bar => 2, a => A.new(foo => 1))
say $b.a;  # A.new(foo => 1)
my $test := $b.a;
say $test; # A.new(foo => 1)

Given $test, how can I access B::bar (which is on the same "level" as $test)?

CodePudding user response:

Personally if I had to do this I'd state that A can have an attribute parent that fulfils a Role HasBar like so.

role HasBar {
    has $.bar = 2;
}

class A {
   has $.foo = 1;
   has HasBar $.parent;
}

class B does HasBar {
    has A $.a;
    submethod TWEAK {
        $!a = A.new( parent => self );
    }
}

Attributes generally don't (and shouldn't) know if they are contained in another object. So if you want to be able to do that you need to tell them the connection exists. I prefer using Roles to do this as then your A class could be an attribute in lots of different things as long as the container has a bar accessible.

CodePudding user response:

You could try this:

class B { ... }            #need to decl B before you use it

class A { 
    has $.foo is rw = 1;   #foo is already =1
    has B $.b;
}                          #no TWEAK needed

class B { 
    has $.bar is rw = 2;
    has A $.a;
}

say my $a = A.new(b => B.new);
say my $b = B.new(a => A.new);
say my $a2 = A.new(b => $b);                
say my $b2 = B.new(a => $a2);

say $a2.b.bar;   #2  
say $b2.a.foo;   #1

$b2.a.b.a.foo = 42;         #added is rw trait to show this
say $b2;

#B.new(bar => 2, a => A.new(foo => 1, b => B.new(bar => 2, a => A.new(foo => 42, b => B))))

If you look at the output you will see that the $b2 is a nested recursion. Not sure if that is what you want! My bet is that @scimon s answer is a better one...

  • Related