Scala构造函数参数的可访问性

17 浏览
0 Comments

Scala构造函数参数的可访问性

需要明确确定Scala构造函数参数的范围

根据此链接(https://alvinalexander.com/scala/how-to-control-visibility-constructor-fields-scala-val-var-private#comment-13237),只要将构造函数参数标记为private,就不会创建getter和setter方法。但是,即使参数被标记为private,我提供的代码仍然可以正常工作。

我看过这个StackOverflow链接(https://stackoverflow.com/questions/14694712/do-scala-constructor-parameters-default-to-private-val?). 这个链接和上面的链接相矛盾。有人能解释一下吗?实际上,代码段可以在StackOverflow链接中找到。

class Foo(private val bar: Int) {
    def otherBar(f: Foo) {
        println(f.bar) // 访问另一个foo的bar
    }
}

下面的代码可以正常运行:

val a = new Foo(1)
a.otherBar(new Foo(3))

它会打印出3。

根据第一个链接,代码应该导致编译错误,因为该参数是private的。

0
0 Comments

问题出现的原因是:构造函数中的参数被声明为类的成员变量,导致在类的其他方法中无法访问该参数。

解决方法是:将构造函数中的参数声明为普通的函数参数,而不是类的成员变量。这样虽然构造函数内部的代码仍然可以访问该参数,但它不是类的成员变量,因此在构造函数外部是不可见的。

以下是整理后的

如果你想要一个只在类内部可见的构造函数参数,不要将其声明为类的成员变量,而是将其声明为普通的函数参数:

class Foo(bar: Int) {
  def otherBar(f: Foo) {
    println(f.bar) // 错误:value bar is not a member of Foo
  }
}

构造函数中的所有代码仍然可以访问`bar`,但它不是`Foo`的成员变量,因此在构造函数外部是不可见的。

0
0 Comments

在Scala语言规范中,private修饰符允许在直接封闭模板及其伴生模块或伴生类中进行访问。为了只允许在实例内部进行访问,可以使用修饰符private[this]。以下代码:

class Foo(private[this] val bar: Int) {
  def otherBar(f: Foo) {
    println(f.bar) // access bar of another foo
  }
}

会导致以下错误:

[error] .../src/main/scala/sandbox/Main.scala:9:17: value bar is not a member of sandbox.Foo
[error]       println(f.bar) // access bar of another foo
[error]                 ^
[error] one error found

为什么private[this] val bar比仅使用bar更好?如果只使用bar,它只是一个构造函数参数,在类Foo中不会创建成员变量。原帖的作者问为什么可以从另一个实例访问一个private成员变量。

那么为什么拥有一个成员变量比不拥有更好?这与反射有关吗?创建一个不需要的成员的其他原因是什么?

如果不需要成员变量,就不要使用它。我同意这一点。但据我所理解,原始问题是关于Scala中私有成员可访问性规则的。

感谢Harald的回答!当我们在构造函数参数中说"private val bar: Int"(没有'this')时,将创建一个名为'bar'的私有字段,带有getter和setter方法。如果这样是正确的,那么我在问题中提供的链接需要进行更正。

是的,你链接问题的第一个答案并不完全正确。裸的构造函数参数不会创建一个private val字段,它只是一个在构造函数范围内有效的值,就像任何其他函数参数一样。

0