How to override apply in a case class companion

2019-01-03 08:42发布

So here's the situation. I want to define a case class like so:

case class A(val s: String)

and I want to define an object to ensure that when I create instances of the class, the value for 's' is always uppercase, like so:

object A {
  def apply(s: String) = new A(s.toUpperCase)
}

However, this doesn't work since Scala is complaining that the apply(s: String) method is defined twice. I understand that the case class syntax will automatically define it for me, but isn't there another way I can achieve this? I'd like to stick with the case class since I want to use it for pattern matching.

9条回答
ら.Afraid
2楼-- · 2019-01-03 09:23

I think this works exactly how you want it to already. Here's my REPL session:

scala> case class A(val s: String)
defined class A

scala> object A {
     | def apply(s: String) = new A(s.toUpperCase)
     | }
defined module A

scala> A("hello")
res0: A = A(HELLO)

This is using Scala 2.8.1.final

查看更多
Animai°情兽
3楼-- · 2019-01-03 09:24

Another idea while keeping case class and having no implicit defs or another constructor is to make the signature of apply slightly different but from a user perspective the same. Somewhere I have seen the implicit trick, but can´t remember/find which implicit argument it was, so I chose Boolean here. If someone can help me out and finish the trick...

object A {
  def apply(s: String)(implicit ev: Boolean) = new A(s.toLowerCase)
}
case class A(s: String)
查看更多
太酷不给撩
4楼-- · 2019-01-03 09:30

For the people reading this after April 2017: As of Scala 2.12.2+, Scala allows overriding apply and unapply by default. You can get this behavior by giving -Xsource:2.12 option to the compiler on Scala 2.11.11+ as well.

查看更多
登录 后发表回答