繁体   English   中英

Scala中类参数声明之间的区别

[英]Difference Between class parameter declaration in Scala

有人可以帮助我理解以下两个声明吗

class Person1(name: String, id: Int) { }
class Person2(val name: String, val id: Int) { }
val p1 = new Person1("personOne", 1)
val p2 = new Person2("personTwo", 2)
println(p1.name) // ERROR
println(p2.name) // OK!!

我知道默认情况下参数是val 为什么第一个p1能够返回数据而p2不能这样做

从 Scala 规范正式开始:

形式值参数的范围包括所有后续参数部分和模板 t。 但是,形式值参数可能不构成任何父类或类模板 t 成员的类型的一部分。 定义两个同名的形式值参数是非法的。

参数部分和模板t基本上描述了整个类范围。

在 Scala 的 JVM 实现上,当您在 Scala 中创建类并且不指定val关键字时,编译器会将字段的范围设置为private[this]并且不会创建外部可见性的匹配方法。 含义(感谢@Duelist 的措辞)这些值仅在封闭类的范围内(这包括类方法和任何惰性字段),仅此而已:

class Person1 extends scala.AnyRef {
  <paramaccessor> private[this] val name: String = _;
  <paramaccessor> private[this] val id: Int = _;
  def <init>(name: String, id: Int): yuval.tests.Person1 = {
    Person1.super.<init>();
    ()
  };
  <empty>
};

添加val关键字时:

class Person1 extends scala.AnyRef {
  <paramaccessor> private[this] val name: String = _;
  <stable> <accessor> <paramaccessor> def name: String = Person1.this.name;
  <paramaccessor> private[this] val id: Int = _;
  <stable> <accessor> <paramaccessor> def id: Int = Person1.this.id;
  def <init>(name: String, id: Int): yuval.tests.Person1 = {
    Person1.super.<init>();
    ()
  };
  <empty>
};

def添加到字段中,使它们在封闭类之外可见,从而在使用站点可见。

带有val声明的类参数是类的public val字段。

没有val声明的类参数就像任何其他函数的参数一样。 它是一个常量值,其范围是整个声明。 如果它被类外部可访问的函数(方法或非方法)引用,则它可以从类中“逃脱”。

注意:与此问题的其他答案相反,没有val的类参数不是的字段,尽管它可能以这种方式实现。 https://www.scala-lang.org/old/node/8384.html

注意case class的不同之处在于case class所有参数都是case classpublic val字段,在它们的名称前有或没有显式val字段。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM