加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 私人类的伴侣对象:为什么不是有效的?

发布时间:2020-12-16 09:36:19 所属栏目:安全 来源:网络整理
导读:我需要两个可以互相访问的实例。我很自然地想到一个伴侣对象,它允许访问一个唯一的伴侣类的实例。该类本身我私有,所以用户不能只是创建使用新的实例。 object A { def apply = dual lazy val dual = new A}private class A { //some irrelevant logic...}
我需要两个可以互相访问的实例。我很自然地想到一个伴侣对象,它允许访问一个唯一的伴侣类的实例。该类本身我私有,所以用户不能只是创建使用新的实例。

object A {
    def apply = dual
    lazy val dual = new A
}

private class A {
    //some irrelevant logic...
}

这段代码不编译。我得到:类A转义其定义范围作为A类错误的一部分,我不太明白。我目前的解决方法是使用类应该具有的每个方法声明来定义特征,并使A类扩展该特征,而dual是trait类型,而不是A类。

我在这里错过了什么理论问题?为什么这个禁止?

解决方法

保罗的解决方案是好的(1),但他没有解释错误信息,所以让我试试看。这个问题源自每个方法都需要返回类型的事实。您的原始定义为apply和dual返回一个类A的对象,因此两者的隐式返回类型为A.这意味着A必须对客户端可见 – 他们还可以调用该函数或访问val?而且,由于它们和它们的父对象都是公开的,它们在全球范围内是可见的。但是,您声明为私有,这意味着它不能在其包之外可见。因此,编译器无法解决冲突。

一般规则是函数/成员的所有参数和返回类型必须具有(至少)与引用成员本身*相同的可见性范围。因此,解决这个问题的一个琐碎的方式是减少适用和双重到私有的可见性。这将满足编译器,但不是你:-)

您的解决方案通过将静态返回类型更改为公共特征来解决问题,因此与引用它的成员具有相同的可见性。返回的对象的动态类型仍然是类A,但是这不需要对客户端可见。这是“program to interfaces,not implementations”原理的典型例子。

请注意,要全面应用此原则,可以将A类转换为对象A的私有内部类,从而即使对于同一个包中的其他类,它也是无法访问的:

trait A {
    //...
}

object A {
    def apply: A = dual
    lazy val dual: A = new AImpl

    private class AImpl extends A {
        //some irrelevant logic...
    }

}

*为了迂回,封闭的类/对象可能会降低其成员的可见性,如下所示:

private class Holder {
  def member = new Hidden
}

private class Hidden

会员是公开的,但其附近的类是私人的,有效地将其成员从外部世界隐藏起来。所以编译器在这里没有发出任何投诉。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读