Say I'm defining a simple 2D point class in Scala, and I want to be able to construct it with various types:
class Point(x:Float, y:Float) {
this(x:Double, y:Double) = this(x.toFloat, y.toFloat)
this(x:Int, y:Int) = this(x.toFloat, y.toFloat)
// etc...
}
I want to boil this down using a template, such as:
class Point(x:Float, y:Float) {
this[T](x:T, y:T) = this(x.toFloat, y.toFloat)
}
I know this won't work anyway, since T could be a type for which toFloat isn't defined, but the compiler error I get is:
no type parameters allowed here
Is this just unsupported in Scala? If so, why, and is there any simple way to get around this?
The auxiliary constructor in Scala is used for constructor overloading and defined as a method using this name. The auxiliary constructor must call either previously defined auxiliary constructor or primary constructor in the first line of its body.
Auxiliary constructors are defined by creating methods named this . Each auxiliary constructor must begin with a call to a previously defined constructor. Each constructor must have a different signature. One constructor calls another constructor with the name this .
There are two types of constructor in Scala – Primary and Auxiliary.
The primary constructor of a Scala class is a combination of: The constructor parameters. Methods that are called in the body of the class. Statements and expressions that are executed in the body of the class.
We are allowed to create any number of auxiliary constructors in our Scala class, but a scala class contains only one primary constructor. Auxiliary constructors are defined as methods in the class with the keyword this. We can describe multiple auxiliary constructors, but they must have different parameter lists.
The primary constructor may contain zero or more parameters. If we do not create a constructor in our Scala program, then the compiler will automatically create a primary constructor when we create an object of your class, this constructor is known as a default primary constructor. It does not contain any parameters.
If an apply method does not get define in the class and call this more than one time in the auxiliary constructor, then it will give a compile time error: In Scala, we can also create a primary constructor with a default value. If you don’t provide value, then it will take the default value, which is provided in the primary constructor.
As we can see that there is no constructor defined in the class. In cases when the constructor is not defined explicitly Scala adds a default constructor with no arguments implicitly. So here, there is no need to define a constructor and perform operations inside it.
Scala's class constructors (unlike Java's) can't take type parameters, only the class itself can. As to why Scala made this design choice, I assume the main reason is simplicity.
If you want a secondary "builder" method that is generic, the natural thing to do is define it on the companion object. For example,
object Point {
def build[T : Numeric](x: T, y: T) = {
val n = implicitly[Numeric[T]]
new Point(n.toFloat(x), n.toFloat(y))
}
}
class Point(val x:Float, val y:Float)
val p = Point.build(1, 2) // Companion object's builder
p.x + p.y
Here I've used the Numeric
typeclass to get a generic toFloat
method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With