Synesso
Synesso

Reputation: 38978

Referencing vals in method returning new trait instance inside trait

In the following, I have trouble referencing the trait's offset value within the + method (line 4).

As it is currently written this.offset is always zero. What I want is the offset from the LHS of the + operation.

How should it be done?

trait Side {
  val offset: Int // <- I want to refer to this
  def +(side: Side) = new Object with Side {
    val offset: Int = this.offset + side.offset // but instead `this.offset` is 0
  }
}

case object Left extends Side {
  val offset = -1
}

case object Right extends Side {
  val offset = 1
}

(Left + Right).offset // -> (0 + 1) -> 1
(Right + Left).offset // -> (0 + -1) -> -1

Upvotes: 1

Views: 99

Answers (1)

som-snytt
som-snytt

Reputation: 39577

The following works because Side.this does not refer to the anonymous class under construction.

Anonymity has its privileges.

scala> :pa
// Entering paste mode (ctrl-D to finish)

trait Side {
  val offset: Int
  def +(side: Side) = new Side {
    val offset = Side.this.offset + side.offset
  }
}

// Exiting paste mode, now interpreting.

defined trait Side

scala> new Side { val offset = 1 }
res0: Side = $anon$1@7e070e85

scala> new Side { val offset = 2 }
res1: Side = $anon$1@5f701cd1

scala> res0+res1
res2: Side = Side$$anon$1@188ef927

scala> .offset
res3: Int = 3

First guess, thinking it was a shadowing problem:

scala> :pa
// Entering paste mode (ctrl-D to finish)

trait Side {
  val offset: Int
  def +(side: Side) = new {
    val offset = Side.this.offset + side.offset
  } with Side
}

// Exiting paste mode, now interpreting.

defined trait Side

scala> new Side { val offset = 1 }
res5: Side = $anon$1@3fa76a13

scala> new Side { val offset = 2 }
res6: Side = $anon$1@465fb2a5

scala> res5+res6
res7: Side = Side$$anon$1@7e84d99c

scala> .offset
res8: Int = 3

Ha. Good night and good luck.

Upvotes: 3

Related Questions