How to resolve the error "outer reference shadow" while referring to another object within the class in Scala?

Viewed 222

While following the exercise(Listing 6.1) mentioned in the book, Programming in Scala Ed 5, I am writing the following code in order to create a Rational class that adds two rational numbers:

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

    override def toString = s"$n/$d"

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

When I paste the same code in the Scala-REPL, I get the following error:

7 |        Rational(
  |        ^^^^^^^^
  |        Reference to constructor proxy for class Rational
  |        shadows outer reference to object Rational

I am not able to understand the reference issue and therefore, unable to debug it. I tried understanding this issue but in vain.

The book also considers the same code and the author is apparently able to create objects of this class.

It should be noted that the code compiles successfully but fails in the REPL.

When I try to define a new variable and return it, the code works. I do not understand why:

scala> class Rational (n: Int, d: Int):
     |     require(d != 0)
     |
     |     val numer: Int = n
     |     val denom: Int = d
     |
     |     override def toString = s"$n/$d"
     |
     |     def add(that: Rational) : Rational =
     |         val answer = Rational(
     |             numer * that.denom + denom * that.numer,
     |             denom * that.denom
     |         )
     |         answer
     |
// defined class Rational

Actually, the snippet above does not work, this is some totally random behavior by Scala REPL:

āžœ  learning-scala git:(main) āœ— scala3-repl
scala> class Rational (n: Int, d: Int):
     |     require(d != 0)
     |
     |     val numer: Int = n
     |     val denom: Int = d
     |
     |     override def toString = s"$n/$d"
     |
     |     def add(that: Rational) : Rational =
     |         val answer = Rational(
     |             numer * that.denom + denom * that.numer,
     |             denom * that.denom
     |         )
     |         answer
     |
     |     def lessThan(that: Rational): Boolean =
     |         val answer = this.numer * that.denom < that.numer * this.denom
     |         answer
     |
10 |        val answer = Rational(
   |                     ^^^^^^^^
   |                     Reference to constructor proxy for class Rational
   |                     shadows outer reference to object Rational

scala> class Rational (n: Int, d: Int):
     |     require(d != 0)
     |
     |     val numer: Int = n
     |     val denom: Int = d
     |
     |     override def toString = s"$n/$d"
     |
     |     def add(that: Rational) : Rational =
     |         val answer = Rational(
     |             numer * that.denom + denom * that.numer,
     |             denom * that.denom
     |         )
     |         answer
     |
     |     def lessThan(that: Rational): Boolean =
     |         val answer = this.numer * that.denom < that.numer * this.denom
     |         answer
     |
// defined class Rational

As you can see, the same code first throws error and then accepts it and defines the class. Why is this behavior so indeterministic?

0 Answers
Related