Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala Constructor Confusion - please clarify

I am very confused by Scala Constructors. For example, I have the following classes that represent a tree with operators such as Add and leaf nodes on the tree that are numbers.

abstract class Node(symbol: String) {}

abstract class Operator(symbol: String,
      binaryOp: (Double, Double) => Double ) extends Node(symbol) {
}

class Add(a: Number, b: Number) extends 
      Operator("+", (a: Double, b: Double) => a+b ) {
}

class Number(symbol: String) extends Node(symbol) {
    val value = symbol.toDouble
    def this(num: Double) {
      this(num.toString)
    }
}

I read in one site that what goes in a Scala constructor is automatically immutable (val), but this guy on Stack Overflow said "The input parameters for the constructor are not vals unless you say they are." So that's one contradiction.

Also, I apparently may or may not need to add "val" and "override" into the constructors for some reason? I mean I want everything to be public and immutable and for Add to have a symbol equal to "+", a binaryOp equal to the addition function, and also two numbers a and b. Can someone please explain how to get the constructors to work as expected in Scala in a non-verbose way?

I want to be able to do something like this:

addition = Add(Number(1), Number(2))
addition.binaryOp(addition.a.value, addition.b.value)
like image 490
Michael Lafayette Avatar asked Oct 20 '15 05:10

Michael Lafayette


1 Answers

You are almost there: Every argument to the constructor of a Scala class is thrown away after construction of the class, unless a method of the class uses it. In this case, it is made a private[this] val.

However, you can simply add the val/var keyword in front of your constructor parameter and it will be made a public val/var:

abstract class Node(val symbol: String) {}

Usually, this is not repeated in the constructor for subclasses if the field is already defined in the superclass:

abstract class Operator(symbol: String, // no val here, only pass to super class
      val binaryOp: (Double, Double) => Double) extends Node(symbol) {
}

class Add(val a: Number, val b: Number) extends 
  Operator("+", (a: Double, b: Double) => a+b ) {
}

Now you can access the fields from outside the class:

addition = Add(Number(1), Number(2))
addition.binaryOp(addition.a.value, addition.b.value)
like image 59
gzm0 Avatar answered Nov 02 '22 11:11

gzm0