When we have a case class, we call map the type with the name of the type, e.g.:
case class Foo(value: String)
val value = Some("Yay!")
val foo = value.map(Foo)
But if we also provide a companion object, this stops working value.map(Foo)
and looks like this works: value.map(Foo(_))
. Why?
case class Foo(value: String)
object Foo {}
val value = Some("Yay!")
val foo = value.map(Foo)
println(foo)
ScalaFiddle.scala:5: error: type mismatch;
found : ScalaFiddle.this.Foo.type
required: scala.this.Function1[lang.this.String,?]
val foo = value.map(Foo)
If you don't define object Foo
at all, then the synthetic companion object has the following declaration:
<synthetic> object Foo
extends scala.runtime.AbstractFunction1[String,Foo]
with Serializable
But if you define your own object Foo
as follows
case class Foo(v: String)
object Foo {}
then the declaration of the Foo
object changes accordingly to:
object Foo extends scala.AnyRef with Serializable
and it no longer extend
s Function1
.
The method apply(v: String): Foo
is still automatically generated on Foo
, but it no longer implements the Function1[String, Foo]
interface. If you declare the companion object like this:
object Foo extends (String => Foo) { ... }
then you again can use it in expressions like value.map(Foo)
.
The value.map(Foo(_))
syntax always works, because it's just a shortcut for
value.map(x => Foo.apply(x))
and the closure doesn't care at all about what interfaces are implemented by Foo
, it cares only about the existence of the apply
method.