2

The following class has an auxillary constructor to change one property in an immutable way.

class AccUnit(size: Long, start: Date, direction:Direction, protocol:String) {
    def this(size:Long, that:AccUnit) {this(size, that.start, that.direction, that.protocol)}
}

Compiler returns an errors:

AccUnit.scala:26: error: value start is not a member of trafacct.AccUnit
        def this(size:Long, that:AccUnit) {this(size, that.start, that.direction, that.protocol)}
                                                           ^
AccUnit.scala:26: error: value direction is not a member of trafacct.AccUnit
        def this(size:Long, that:AccUnit) {this(size, that.start, that.direction, that.protocol)}
                                                                       ^
AccUnit.scala:26: error: value protocol is not a member of trafacct.AccUnit
        def this(size:Long, that:AccUnit) {this(size, that.start, that.direction, that.protocol)}

Why does it think, there is no such members?

Basilevs
  • 22,440
  • 15
  • 57
  • 102

2 Answers2

7

Because it should be

class AccUnit(val size: Long, val start: Date, val direction:Direction, val protocol:String) {...}

or

case class AccUnit(size: Long, start: Date, direction:Direction, protocol:String) {...}

In your version, size and others are only constructor arguments, but not members.

UPDATE: You can check it yourself:

// Main.scala
class AccUnit(size: Long, protocol: String)

F:\MyProgramming\raw>scalac Main.scala

F:\MyProgramming\raw>javap -private AccUnit
Compiled from "Main.scala"
public class AccUnit extends java.lang.Object implements scala.ScalaObject{
    public AccUnit(long, java.lang.String);
}
Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • The last sentence is incorrect I think, they are members but they are private. scala> class AccUnit(size: Long,start: Date,direction:Direction,protocol:String) { override def toString = "size: " + size +", start: " + start } scala> new AccUnit(1,new Date(), new Direction(), "test") res2: AccUnit = size: 1, start: Tue Oct 19 20:37:44 CEST 2010 – oluies Oct 19 '10 at 18:38
  • They become members automatically if they are used in the body of the class :) – Alexey Romanov Oct 19 '10 at 20:10
  • Hmm, WFT... AHA... do you have any reference to doc? Chapter 6.5 in "Programming in Scala" – oluies Oct 19 '10 at 21:22
  • Looked in the Scala reference, and I don't see a clear statement. Perhaps ask in the scala-user mailing list? – Alexey Romanov Oct 20 '10 at 07:03
6

If you're using Scala 2.8, then a better solution is to use the copy method defined on case classes, which takes advantage of the named/default parameters feature:

case class AccUnit(size: Long, start: Date, direction:Direction, protocol:String)

val first = AccUnit(...)
val second = first.copy(size = 27L)
Kevin Wright
  • 49,540
  • 9
  • 105
  • 155