简体   繁体   English

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

[英]Difference Between class parameter declaration in Scala

can some one help me in understand the below two declarations有人可以帮助我理解以下两个声明吗

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!!

I know that by default the parameters are val .我知道默认情况下参数是val Why the first p1 is able to return data and p2 could not do the same为什么第一个p1能够返回数据而p2不能这样做

Starting formally from the Scala specification:从 Scala 规范正式开始:

The scope of a formal value parameter includes all subsequent parameter sections and the template t.形式值参数的范围包括所有后续参数部分和模板 t。 However, a formal value parameter may not form part of the types of any of the parent classes or members of the class template t.但是,形式值参数可能不构成任何父类或类模板 t 成员的类型的一部分。 It is illegal to define two formal value parameters with the same name.定义两个同名的形式值参数是非法的。

The parameter sections and the template t basically describes the entire class scope.参数部分和模板t基本上描述了整个类范围。

On the JVM implementation of Scala, when you create a class in Scala and don't specify the val keyword, the compiler sets the scope of the field to private[this] and doesn't create a matching method for outer visibility.在 Scala 的 JVM 实现上,当您在 Scala 中创建类并且不指定val关键字时,编译器会将字段的范围设置为private[this]并且不会创建外部可见性的匹配方法。 Meaning (thanks @Duelist for the wording) the values are only in scope for the enclosing class (this includes class methods and any lazy fields), nothing more:含义(感谢@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>
};

When you add the val keyword:添加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>
};

A def is added to the fields which makes them visible outside of the enclosing class, thus visible from at the use site.def添加到字段中,使它们在封闭类之外可见,从而在使用站点可见。

A class parameter with a val declaration is a public val field of the class.带有val声明的类参数是类的public val字段。

A class parameter without a val declaration is just like a parameter to any other function.没有val声明的类参数就像任何其他函数的参数一样。 It is a constant value whose scope is the whole of the declaration.它是一个常量值,其范围是整个声明。 It can "escape" from the class if it is referenced by a function that is accessible outside the class (method or non-method).如果它被类外部可访问的函数(方法或非方法)引用,则它可以从类中“逃脱”。

Note : Contrary to other answers to this question, a class parameter without a val is not a field of the class, though it may be implemented that way.注意:与此问题的其他答案相反,没有val的类参数不是的字段,尽管它可能以这种方式实现。 See https://www.scala-lang.org/old/node/8384.htmlhttps://www.scala-lang.org/old/node/8384.html

Note : A case class is different in that all parameters to a case class are public val fields of that class, with or without an explicit val before their name.注意case class的不同之处在于case class所有参数都是case classpublic val字段,在它们的名称前有或没有显式val字段。

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

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