Scala 中的好友访问

Friend access in Scala

考虑

在 Scala 中,是否可以声明 f 可从包 p2 而不是其他包(例如 p3)访问?

如果我将您的规则扩展到极限,这是可能的。虽然我不确定这是有意为之还是您忘记了规则。

scala> :paste -raw
// Entering paste mode (ctrl-D to finish)

package p1 {
  object O { private[p1] def f = println("f") }

  package p2 {
    object O { def x = p1.O.f }
  }
}

// Exiting paste mode, now interpreting.


scala> :paste -raw
// Entering paste mode (ctrl-D to finish)

package p3 {
  object O { def x = p1.O.f }
}

// Exiting paste mode, now interpreting.

<pastie>:2: error: method f in object O cannot be accessed in object p1.O
  object O { def x = p1.O.f }
                          ^
There were compilation errors!

如果 p2 也不能被 p1 包含,我认为没有办法保证 f 不能从其他地方访问。您可以使用密封的特征和隐含技巧。

package p2 {
  object O { def x = p1.O.f }
}

package object p2 {
  sealed trait Friend
  private[p2] implicit val p2Friend: Friend = new Friend {}
}

package p1 {
  object O { def f(implicit friend: p2.Friend) = println("f") }
}

package p3 {
  object O { def x = p1.O.f(null) }
}

但现在如您所见,您仍然可以在包 p3 中作弊。如果不作弊 f 无法在 p1 本身中访问,因为 p1 也没有必要的隐式。

您可以在 f 中检查 friend 是否为 null。那么 p3 并不能真正使用 f 但它只会在运行时失败,而不会在编译时失败。虽然如果有人路过 null 如果事情在运行时爆炸,他们不能真正抱怨。