Scala: is it possible to override default case class constructor?
Asked Answered
V

4

21

Just wondering if this is possible. What I would actually like to do is check and possibly modify one of the arguments before it is stored as a val.

Alternatively, I could use an overload and make the default constructor private. In which case I would also like to make private the default factory constructor in the companion object, how would I do that?

Many thanks.

Adam

edit: well i figured out that making the default constructor private also makes the default factory constructor private, so i have a solution, i'm still interested to know if the default constructor is overridable though

Vitellin answered 18/4, 2010 at 3:11 Comment(2)
Why do you want to do this? A case class is meant to be used to define algebraic data types, so an added constructor that alters the caller's arguments a bit of a lie. As far as validating arguments goes, that can be done in the primary constructor using assert or require.Irreproachable
@Vitellin To reframe your initial statement as a question, "Can I check and possibly modify a [case class parameter]?" The answer is yes. I just posted the details on a related question located here: https://mcmap.net/q/76157/-how-to-override-apply-in-a-case-class-companionBackhand
I
11

The presence of secondary case class constructors don't cause the compiler to produce additional factory methods in the class's companion, so you won't get the convenience of CaseClaseName(«secondary constructor parameter list»>) for creating them. You'll have to use the new keyword.

It's better to put the sort of logic you're describing in alternate factory methods in the companion object and stick to using the primary constructor.

Irreproachable answered 3/9, 2010 at 15:16 Comment(0)
K
25

You do not have the option of changing the way the default constructor stores its parameters (e.g. by modifying the parameters before they are stored as vals) but you do have the option of throwing an exception if the parameters are wrong (this will occur after the parameters are stored)

case class Foo(x:Int){
    if (x<0) throw SomeException;
}

You also have the option of implementing additional constructors that call the first constructor

case class Foo(x:Int){
     def this(x:Int,y:Int) = this(x+y)
}

but those don't get factory methods.

You could easily create the factory method yourself by adding it to the companion object

object Foo{
     def apply(x:Int,y:Int) = new Foo(x,y)
}

Anything else more complicated than that, and you have to forgo the case class and implement it's parts on your own: apply, unapply, equals, and hashCode. Programming in Scala talks about how to do all of these, giving good formulas for equals and hashCode.

Klingel answered 8/9, 2010 at 1:25 Comment(1)
It is possible to safely change parameters before they are stored in the case class. And you can still do quite a few more complicated things without forgoing all the benefits of case classes. I have just detailed my solution on another thread: https://mcmap.net/q/76157/-how-to-override-apply-in-a-case-class-companionBackhand
I
11

The presence of secondary case class constructors don't cause the compiler to produce additional factory methods in the class's companion, so you won't get the convenience of CaseClaseName(«secondary constructor parameter list»>) for creating them. You'll have to use the new keyword.

It's better to put the sort of logic you're describing in alternate factory methods in the companion object and stick to using the primary constructor.

Irreproachable answered 3/9, 2010 at 15:16 Comment(0)
P
3

You can overload constructors. It's the same as in C++ or Java. Simply make another constructor.

class Foo( _input:Int ){
    def this() = this( 0 )
}

Or you can see this SO post.

Presentationism answered 18/4, 2010 at 3:40 Comment(2)
Thanks, but the question is override not overload.Vitellin
No constructor can be overridden, since they're not inherited to begin with.Irreproachable
B
1

You can turn a regular class into a pseudo-case-class by writing your own apply (for the factory) and unapply (for the pattern match) methods in the companion object. Or, you could simply write a named factory method in the case class's companion object.

Bootstrap answered 5/9, 2010 at 2:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.