tags:

views:

221

answers:

2

I'm learning Scala, and I can't figure out how to best express this simple Java class in Scala:

public class Color {
  public static final Color BLACK = new Color(0, 0, 0);
  public static final Color WHITE = new Color(255, 255, 255);     
  public static final Color GREEN = new Color(0, 0, 255);

  private final int red;
  private final int blue;
  private final int green;

  public Color(int red, int blue, int green) {
    this.red = red;
    this.blue = blue;
    this.green = green;
  }

  // getters, et cetera
}

The best I have is the following:

class Color(val red: Int, val blue: Int, val green: Int)
object BLACK extends Color(0, 0, 0)
object WHITE extends Color(255, 255, 255)
object GREEN extends Color(0, 0, 255)  

But I lose the advantages of having BLACK, WHITE, and GREEN being tied to the Color namespace.

+6  A: 

You could just put the specific colors into the companion object:

class Color(val red: Int, val blue: Int, val green: Int)
object Color {
  object BLACK extends Color(0, 0, 0)
  object WHITE extends Color(255, 255, 255)
  object GREEN extends Color(0, 0, 255)
}

EDIT:

Alternatively, you could have vals within the companion object:

class Color(val red: Int, val blue: Int, val green: Int)
object Color {
  val BLACK = new Color(0, 0, 0)
  val WHITE = new Color(255, 255, 255)
  val GREEN = new Color(0, 0, 255)
}

You could make them lazy to defer instantiation until they are used:

class Color(val red: Int, val blue: Int, val green: Int)
object Color {
  lazy val BLACK = new Color(0, 0, 0)
  lazy val WHITE = new Color(255, 255, 255)
  lazy val GREEN = new Color(0, 0, 255)
}

Going back the original solution, you could prevent extension of the class (simulating "final" by making the Color class sealed:

sealed class Color(val red: Int, val blue: Int, val green: Int)
object Color {
  object BLACK extends Color(0, 0, 0)
  object WHITE extends Color(255, 255, 255)
  object GREEN extends Color(0, 0, 255)
}
Mitch Blevins
(I'm not a Scala person. Does that work for "final" classes?)
Tom Hawtin - tackline
You cannot extends a final class, but you could make it "sealed" so that it cannot be extended outside of the current compilation unit.
Mitch Blevins
+8  A: 
case class Color(red: Int, blue: Int, green: Int)

object Color {
  val BLACK = Color(0, 0, 0)
  val WHITE = Color(255, 255, 255)
  val GREEN = Color(0, 0, 255)
}
missingfaktor
As an aside note, the Scala convention is to use PascalCase for constants, such as `Black`.
missingfaktor