This page is no longer maintained — Please continue to the home page at www.scala-lang.org

apply in case class and companion object

1 reply
Rüdiger Klaehn
Joined: 2009-06-02,
User offline. Last seen 42 years 45 weeks ago.

Hi all,

I would like to have an apply method in a companion object with the
same signature as the (private) main constructor of the case class.
The reason I want to do this is that I want to "normalize" the data in
the companion object apply method.

Simple example:

case class Range private (min:Double, max:Double)

object Range {
def apply(min:Double, max:Double) =
if(min>max)
empty
else
Range(min,max)

def empty=Range(Double.PositiveInfinity, Double.NegativeInfinity)
// this is the only allowed range where min>max
}

The problem is that I get a compiler error "error: method apply is
defined twice" because the case class constructor is an automatically
generated apply method. So far I have been avoiding the problem by
renaming the factory method in the companion object "make", but that
is kind of ugly. Another option would be a third (dummy) parameter in
the case class constructor, but that would be an unused field in the
class that would also be considered for toString, equals and hashCode,
right?

You might say that I don't want a case class at all, since the two
fields min and max are not completely independent of each other. But
then I would have to write my own hashCode, equals, toString, unapply,
copy, ..., which seems a bit excessive for such a simple class.

Is there a way to get methods automatically generated without using a
case class?

Any ideas?

Rüdiger

bjohanns
Joined: 2009-10-23,
User offline. Last seen 1 year 37 weeks ago.
Re: apply in case class and companion object

Hi Rüdiger,
>
> I would like to have an apply method in a companion object with the
> same signature as the (private) main constructor of the case class.
> The reason I want to do this is that I want to "normalize" the data in
> the companion object apply method.
>

maybe this will do the trick:

Welcome to Scala version 2.8.0.final (GNU libgcj, Java 1.5.0).
Type in expressions to have them evaluated.
Type :help for more information.

object Main {
case class X[T <% Int] (a: T, b: String) {
private val secret = "its my companion!";
}

object X {
def apply (a: Int, b: String): X[Int] = {
val result = new X[Int](a,b);
println("asking: " + result.secret);
result;
}
}
}

scala> import Main._
import Main._

scala> X(1, "foo")
asking: its my companion!
res1: Main.X[Int] = X(1,foo)

scala> X[Int](2, "bar")
res2: Main.X[Int] = X(2,bar)

As I understand it the view bound helps to disambiguate the companion apply
from the case class apply. So you can "select" by typing which one you want to
use. However this trick might come with a runtime penalty... I did'nt check
(and I am still new to scala myself...)
Declaring the case class constructor as private might be good (to force any
non-copy construction through the companion)

strangely at least in the REPL it seems to work out of the box OK. That's why
I put the example above into an object to simulate a package.

scala> case class X (a: Int, b: String)
defined class X

scala> object X {
def apply (a: Int, b: String): X = {
println("companion"); new X(a,b)
}
}
defined module X

scala> println(X(1,"a"))
companion
X(1,a)

Greetings - Bernd

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland