混淆scala私有字段变量

混淆scala私有字段变量,scala,Scala,我在scala学习的第三天。使用“开始scala”一书 作者使用一个示例来显示变量定义为val var和不定义var val之间的差异: class Book(private val title: String) { def printTitle(b: Book) { println(b.title) } } 在控制台中: scala> val book = new Book("Beginning Scala") book: Book = Book@ea05be

我在scala学习的第三天。使用“开始scala”一书

作者使用一个示例来显示变量定义为val var和不定义var val之间的差异:

class Book(private val title: String) {
   def printTitle(b: Book) {
       println(b.title)
   }
}
在控制台中:

scala> val book = new Book("Beginning Scala")
book: Book = Book@ea05be
scala> book.printTitle(new Book("Beginning Erlang"))
Beginning Erlang
这里让我困惑的不是val var,而是私有修饰符:


我不确定我是否理解私有权利,但如果scala希望将标题作为私有字段,那么为什么它允许其他人从外部访问它,我认为prinTitle不应该能够访问新书(“开始Erlang”)的标题字段值
title
对类是私有的,不适用于实例,因为方法
printTitle
是类的成员,所以它可以访问其他实例的私有值

如果希望
title
对实例是私有的,则可以使用
private[this]
修饰符

此外,
private[package]
修饰符可以与包共享私有成员,其中
package
是定义所在的包的名称。比如说

package com.sample.foo

class Book(private[foo] title: String)

com.sample.foo中的所有代码都可以访问
title
是类
Book
的私有字段

在Java中,您可以这样编写:

class Book {
    private final String title;

    Book(String title) {
        this.title = title;
    }

    public void printTitle(b: Book) {
       System.out.println(b.title)
    }
 }
我认为函数
printTitle
可能有些混乱,因为在java和scala中,它通常不会作为实例方法实现。 我会用java编写这样的静态方法。在scala中,我会把它放在一个伴星对象中(向一个困惑的scala newby抛出另一个外星人概念;):

所以Book可以访问Book实例的任何私有字段

如果您想限制对书籍实例的标题访问,您可以编写如下内容:

class Book(private[this] val title: String) {
   // no longer compiles
   // def printTitle(b: Book) {
   //    println(b.title)
   //}

   def printTitle() {
       println(title)
   }
}

谢谢我想我可能需要一点时间来理解这一切。为了验证我是否正确理解您的意思:“值标题对类是私有的,而不是对实例”是否理解为“值标题对其他类类型是私有的,而不是对从该类生成的实例”?@Kuan Correct。其目的是实例已经知道彼此的内部结构,因为它们是同类的,因此可以访问它们。但是因为有时候你真的想严格控制内部,所以私有[this]修饰符的存在只是为了限制对实例的访问,为了验证我理解类如何正确工作:我能理解Scala类中的所有字段都是通过getter和setter函数访问的,而不是直接访问该变量吗?所以PRIVATE限制对getter setter函数的访问(我不确定它是只允许memeber方法,还是完全删除getter setter),以使外部世界无法访问该变量?谢谢。读完这篇文章后,我觉得私有的概念在JAVA和Scala中是不同的(这里它更复杂、更灵活)
class Book(private[this] val title: String) {
   // no longer compiles
   // def printTitle(b: Book) {
   //    println(b.title)
   //}

   def printTitle() {
       println(title)
   }
}