score:0

A parameter of a class is visible in its body. It will be made a private val if need be, that is if it is used in a method, and not just in the initialization code (and of course if it is not directly declared a val with a different visibility, or a var).

So changedParam in Child shadows the one in Base. The obvious way to avoid that is simply to call it another name:

class Child(anotherName: MyClass) extends Base(doStuff(anotherName)) {...

score:0

This is considered brittle and annoying.

You get a little relief if you're shadowing a var:

scala> class A { var a = 1 } ; class B(a: Int) extends A { def f = a }
defined class A
defined class B

scala> val b = new B(42) ; b.a = 7 ; b.f
b: B = B@1376c05c
b.a: Int = 7
res0: Int = 42

scala> :replay -Xlint
Replaying: class A { var a = 1 } ; class B(a: Int) extends A { def f = a }
<console>:7: warning: private[this] value a in class B shadows mutable a inherited from class A.  Changes to a will not be visible within class B - you may want to give them distinct names.
       class A { var a = 1 } ; class B(a: Int) extends A { def f = a }
                                                                   ^
defined class A
defined class B

Replaying: val b = new B(42) ; b.a = 7 ; b.f
b: B = B@f2ff811
b.a: Int = 7
res0: Int = 42

Normally, shadowing a val is more benign, but a warning for your example would be useful.

score:0

1) Using explicit call to Parent with asInstanceOf:

package demo {
  // remove protected or make it protected[demo]
  class Parent(protected[demo] val changedParam: MyClass)

  class Child(changedParam: MyClass)
    extends Parent(doStuff(changedParam)) {
    def foo() = {
      bar(this.asInstanceOf[Parent].changedParam)
    }
  }
}

2) Using early initializers syntax:

class Parent(protected val changedParam: MyClass)

class Child(changedParam: MyClass) extends {
  val superChangedParam = doStuff(changedParam)
} with Parent(superChangedParam) {
  def foo() = {
    bar(superChangedParam)
  }
}

Nevertheless the best solution is to give a different name to your param.

score:0

class Parent(protected val changedParam: MyClass)

trait Child extends Parent {
  def foo() = {
    bar(changedParam)
  }
}

object Child {
  def apply(changedParam: MyClass): Child =
    new Parent(doStuff(changedParam)) with Child
}

Not much to say... Turning Child into a trait avoids to declare a new temporary member that you don't want to be used after the initialization. Then I used the companion object to declare the constructor. The only difference in usage is that you don't have to add the new keyword to instanciate Child.

Test:

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

class Parent(protected val changedParam: Int)

trait Child extends Parent {
  def foo() = {
    println(changedParam)
  }
}

object Child {
  def apply(changedParam: Int): Child =
    new Parent(1 + changedParam) with Child
}

// Exiting paste mode, now interpreting.

defined class Parent
defined trait Child
defined object Child

scala> Child(42).foo()
43

Related Query

More Query from same tag