【问题标题】:Private attribute in class makes typed public attributes undefined类中的私有属性使类型化的公共属性未定义
【发布时间】:2018-10-08 06:47:06
【问题描述】:

我正在编写一个如下所示的类:

class ListenSocket is Tap {
    has         $!VMIO;
    has Promise $.socket-host;
    has Promise $.socket-port;

    method new(&on-close, Mu :$VMIO, Promise :$socket-host, Promise :$socket-port) {
        self.bless: :&on-close, :$VMIO, :$socket-host, :$socket-port;
    }

    submethod BUILD(Mu :$!VMIO) { }
}

当我尝试使用为 $socket-host 和 $socket-port 定义的 Promises 构造类时,无论出于何种原因,它们在类中的属性最终都变得未定义。我该怎么做才能解决这个问题?

【问题讨论】:

  • 可能是由于您拥有的空方法 BUILD 。 bless 实际上调用它。如果您的定义如此简单,最好不要定义任何内容,或者将其留给 BUILD 而不是定义 new
  • 如果您将BUILD 的名称更改为TWEAK,这可能会更好
  • 因为&on-close 是Tap 的私有成员,所以这些都不起作用

标签: raku


【解决方案1】:

我应该从 Liz 写的开始。将BUILD 切换为TWEAK。然后默认的BUILD 将完成它的工作,并且您的套接字属性将被正确初始化。

下一个问题是&on-close。请参阅Lizmat's answer to Constructors in subclases 显示如何处理该问题,如果您可以修改超类(在本例中为 Tap)或 Jonathan's authoritative answer to Inheriting private attributes in Perl 6(这是关于对另一个类的属性的任何访问),如果您 不能修改超类。


请注意,上述两个问题实际上与类中的“私有属性”无关,从而使“公共属性”未定义。类型也不相关。

所有属性在技术上都是私有的。私有/公共的区别在于是否有私有属性的公共访问器。

您的自定义BUILD 只是初始化$!VMIO,它没有公共访问器。您忽略了初始化$!socket-host 和$!socket-port,这些属性 具有公共访问器(由于在声明它们时使用了the public accessor twigil .)。

您可能编写了自定义BUILD,因为默认BUILD 仅使用公共访问器初始化属性。但是,如果这样做,您将承担对象构造的全部责任,并且您必须初始化所有要初始化的属性。

最好写一个TWEAK。然后你可以只处理 没有 公共访问器的属性。 TWEAK 只是向BUILD 添加进一步的初始化,对于默认的BUILD,它只是使用公共访问器的属性的初始化。

【讨论】:

  • 这仍然不适用于$!VMIO,即使我将它添加到BUILD。它确实适用于 $.socket-host 和 $.socket-port 虽然
  • 但是,将 $!VMIO 和 $.socket-port 添加到 BUILD 确实可以解决此问题,因此如果您可以编辑答案,那就太好了
  • *$!VMIO 和 $.socket-port 第一条评论
  • 答案完全重写。
猜你喜欢
  • 2013-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-09
  • 2014-02-16
相关资源
最近更新 更多