4

I'm confused by the following:

class A(val s: String) {
 def supershow {
   println(s)
 } 
}


class B(override val s: String) extends A("why don't I see this?"){
  def show {
    println(s)
  }
  def showSuper {
    super.supershow
  }
}

object A extends App {
  val b = new B("mystring")
  b.show
  b.showSuper
}

I was expecting:

mystring
why don't I see this?

But I get:

mystring
mystring

In java if you override, or 'shadow' a variable in a super class, the super class has its own variables. But here, even though I think I'm explicitly initializing the parent with a different string, the parent gets set to the same value as the subclass?

Bruce
  • 2,406
  • 5
  • 29
  • 35

1 Answers1

9

In scala val is similar to getter method in java. You can even override def with val.

If you need something similar to field from java you should use private[this] val:

class A(private[this] val s: String) {
  def superShow() = println(s)
}
class B(private[this] val s: String) extends A("why don't I see this?") {
  def show() = println(s)
}

val b = new B("message")
b.show
// message
b.superShow()
// why don't I see this?
senia
  • 37,745
  • 4
  • 88
  • 129
  • Thank you. That's useful, although I'm completely confused now about val and var and override. Do you know of a clear description of how they all work and the philosophy behind it? At the moment, it's all a big muddle in my head - it seems like lots of special rules for different situations like this from the scala cookbook "As shown in the example, fields of a trait can be declared as either var or val. You don’t need to use the override keyword to override a var field in a subclass (or trait), but you do need to use it to override a val field".I can't find the underlying consistency. Thanks! – Bruce Nov 13 '13 at 11:04
  • @Bruce: I'm pretty sure that there is such answer on SO. `def` - method. `val` - "stable" method (getter), initialized in constructor. `var varName: T` - pair of methods `def varName: T` and `def vatName_=(T): Unit`. `lazy val` - "stable" method implemented as double check lock. You can override `def` with any of {`def`, `val`, `var`, `lazy val`}, you can also override `lazy val` with `val`. – senia Nov 13 '13 at 11:12
  • Thank you. I've been reading a number of scala books and haven't yet seen val described as a method or even as like a method. However, the way you describe it seems like it's a good way of looking at things, and may well help me to understand it.. Thanks for your help! – Bruce Nov 13 '13 at 11:18
  • @Bruce: See [uniform access principle](http://joelabrahamsson.com/learning-scala-part-nine-uniform-access/). – senia Nov 13 '13 at 11:22
  • Fantastic, thanks - I'll check this out. Looks like a good series of articles. – Bruce Nov 13 '13 at 11:28
  • @Bruce: I don't know, I didn't read this series. I've just googled it on "scala uniform access principle". – senia Nov 13 '13 at 11:30
  • By the way, I tested out the overrides you say are possible above. On my compiler, I couldn't get var to override def - seems to be a known issue with scala: https://issues.scala-lang.org/browse/SI-2338 and I couldn't get val to override lazy val - I get the compiler error 'value name must be declared lazy to override a lazy concrete value' – Bruce Nov 13 '13 at 15:28
  • @Bruce: it's my mistake. You can override **abstract** `val` with `lazy val`. – senia Nov 13 '13 at 17:18
  • @Bruce: `I couldn't get var to override def` You can override **abstract** `def` with `var`. – senia Nov 13 '13 at 17:30
  • Thanks Senia. Your help was part of a productive path today for me - I learned some useful stuff about scala and how it works.. Thanks again. – Bruce Nov 13 '13 at 17:52