简体   繁体   中英

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 . Why the first p1 is able to return data and p2 could not do the same

Starting formally from the Scala specification:

The scope of a formal value parameter includes all subsequent parameter sections and the template 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. 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.

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. 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:

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:

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.

A class parameter with a val declaration is a public val field of the class.

A class parameter without a val declaration is just like a parameter to any other function. 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. See https://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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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