Perl 6技术疑问:如何在运行时为变量混入抽象role?
如何在Perl 6运行时混入的Role中访问原类的属性
你遇到的问题核心在于:$!word是Bare-Word类的私有属性,而你在mixin的role里直接引用它——role在定义时并不知道它会被混入哪个类,编译器自然会报错说这个属性在role中未声明。下面是具体的解决方案和原理说明:
解决方案1:通过公共访问器方法访问
因为你在Bare-Word里定义了has $.word,Perl 6会自动为这个属性生成一个公共的.word访问器方法。在混入的role中,你可以通过self.word调用这个方法来获取属性值:
role jsonable { method to-json( ) { ... } } class Bare-Word { has $.word; # 注:你自定义的new方法可以省略,Perl 6会自动生成接受word参数的构造函数 # method new ( Str $word ) { return self.bless( $word ); } } my $that-word = Bare-Word.new( "Hola" ) but role jsonable { method to-json() { return "['{self.word}']"; } }; # 测试验证 say $that-word.to-json; # 输出:['Hola']
为什么原来的写法不行?
$!word这种语法是用来访问当前类/role自身的私有属性的。你的mixin role是在Bare-Word类外部定义的,role本身并没有声明$!word属性,所以编译阶段就会报错。而self.word是调用实例的公共方法,这个方法由Bare-Word类提供,混入role后的实例自然继承了这个方法,因此可以正常访问属性值。
如果属性是纯私有(无访问器)怎么办?
如果你的属性是纯私有(比如has $!word,没有$.前缀),可以通过限定符强制访问,但这种方式耦合度很高,不推荐在生产代码中使用:
my $that-word = Bare-Word.new( "Hola" ) but role jsonable { method to-json() { return "['{self!Bare-Word::word}']"; } };
更优雅的做法是给私有属性添加一个私有访问器方法,或者直接改用公共属性,让代码逻辑更清晰易懂。
内容的提问来源于stack exchange,提问作者jjmerelo
相关产品推荐
相关产品推荐

