Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

258
Visualizações
Scala: Class parameters access vs object fields access

I am coming from Java background and new to Scala, currently going through the book 'Programming in Scala'.

There is an example in the book as below:

class Rational(n: Int, d: Int) { // This won't compile
  require(d != 0)
  override def toString = n + "/" + d

  def add(that: Rational): Rational = new Rational(n * that.d + that.n * d, d * that.d)
}

However, given this code the compiler complains:

error: value d is not a member of Rational
       new Rational(n * that.d + that.n * d, d * that.d)
                             ^
error: value n is not a member of Rational
       new Rational(n * that.d + that.n * d, d * that.d)
                                      ^
error: value d is not a member of Rational
       new Rational(n * that.d + that.n * d, d * that.d)
                                                      ^

The explanation says:

Although class parameters n and d are in scope in the code of your add method, you can only access their value on the object on which add was invoked. Thus, when you say n or d in add's implementation, the compiler is happy to provide you with the values for these class parameters. But it won't let you say that.n or that.d because that does not refer to the Rational object on which add was invoked. To access the numerator and denominator on that, you'll need to make them into fields.

Also the correct implementation is given as below:

class Rational(n: Int, d: Int) {
  require(d != 0)
  val numer: Int = n
  val denom: Int = d

  override def toString = numer + "/" + denom

  def add(that: Rational): Rational =
    new Rational(
      numer * that.denom + that.numer * denom,
      denom * that.denom
    )
}

I tried to understand this many times, but still not clear.

I already have the n and d parameters at class level. I am able to access them in add method. I am passing another Rational object to the add method. It should also be having n and d, right?

What is wrong with that.n and that.d? Why do I need to take the parameters in fields?

Also, the overridden toString method is simply taking n and d, how does that not fail?

I may sound stupid, but really need to understand this clearly for better fundamentals before I move ahead.

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Parameters passed to a class constructor defaults to private members and thus are are available to all the class code (as seen in the toString override) but they are not accessible as instance members (so that.d doesn't work).

You can tell the compiler not to use the default.

class Rational(val n: Int, val d: Int) { // now it compiles
  ...

Alternatively, arguments passed to a case class default to instance members.

case class Rational(n: Int, d: Int) { // this also compiles
  ...
over 4 years ago · Santiago Trujillo Relatório

0

Scala has more types of access modifiers than Java. In Scala there's a thing called private[this] which means "private to the current object" which is stricter than the normal private which means "private to all objects of this class".

class Rational(n: Int, d: Int)

is basically the same as

class Rational(private[this] val n: Int, private[this] val d: Int)

At a higher, almost philosophical level you could say that

class Rational(n: Int, d: Int) { ... }

is like a static method returning a Rational and it has parameters n and d, and as in any method its parameters are local to the method. By qualifying the parameters with val or var you turn those parameters into fields of the Rational, without having to write them twice: once as a parameter to the method (or constructor, which is the more specific name for this static method), and once as a field.

over 4 years ago · Santiago Trujillo Relatório

0

I was reading the same book and I had the same doubt. When I decompiled the code, this is what got generated.

class Employee(var age: Int)

transpiled to

public class Employee {
   private int age;

   public int age() {
      return this.age;
   }

   public void age_$eq(final int x$1) {
      this.age = x$1;
   }

   public Employee(final int age) {
      this.age = age;
      super();
   }
}

Next,

class Employee(val age: Int)

transpiled to

public class Employee {
   private final int age;

   public int age() {
      return this.age;
   }

   public Employee(final int age) {
      this.age = age;
   }
}

Next,

class Employee(age: Int)

transpiled to

public class Employee {
   public Employee(final int age) {
   }
}
  • There seems to be a Constructor of the class Employee, with just a parameter named age. That clearly shows that age doesn't get attached to the instance of Employee. There is no instance attribute named age on Employee.
  • However, if we add a simple getter of age, this generates a private final attribute for the same.

Example

class Employee(age: Int) {
  def getAge(): Int = age
}

transpiled to

public class Employee {
   private final int age;

   public int getAge() {
      return this.age;
   }

   public Employee(final int age) {
      this.age = age;
   }
}
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda