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...