I am trying to create a Vector class that is generic for all numeric types. my original attempt was to write a class for all Types like this:
class Vector3f(val x:Float, val y:Float, val z:Float)
since scala supports the specialised annotation I could use this to generate me these classes for all numeric types
class Vector3[A <: What?](val x:A,val y:A, val z:A)
but everything I found as a super type for numbers was AnyVal, but AnyVal does not support + - * /. So what is the right way to do this, but without sacrificing the performance of unboxed number types?
To update the Box class to use generics, you create a generic type declaration by changing the code "public class Box" to "public class Box<T>". This introduces the type variable, T, that can be used anywhere inside the class. As you can see, all occurrences of Object are replaced by T.
Java Generic Classes and SubtypingWe can subtype a generic class or interface by extending or implementing it. The relationship between the type parameters of one class or interface and the type parameters of another are determined by the extends and implements clauses.
Like C++, we use <> to specify parameter types in generic class creation. To create objects of a generic class, we use the following syntax. Note: In Parameter type we can not use primitives like 'int','char' or 'double'.
A Generic class simply means that the items or functions in that class can be generalized with the parameter(example T) to specify that we can add any type as a parameter in place of T like Integer, Character, String, Double or any other user-defined type.
You can't. Not right now. Maybe when, and if, Numeric
gets specialized.
Say you get the simplest parameterized class possible:
class Vector3[@specialized T](val x: T, val y: T, val z: T)(implicit num: Numeric[T]) { def +(other: Vector3[T]) = new Vector3(num.plus(x, other.x), num.plus(y, other.y), num.plus(z, other.z)) }
The method +
will compile into something roughly like this:
override <specialized> def +$mcD$sp(other: Vector3): Vector3 = new Vector3$mcD$sp( scala.Double.unbox( Vector3$mcD$sp.this.Vector3$$num.plus( scala.Double.box(Vector3$mcD$sp.this.x()), scala.Double.box(other.x$mcD$sp()))), scala.Double.unbox( Vector3$mcD$sp.this.Vector3$$num.plus( scala.Double.box(Vector3$mcD$sp.this.y()), scala.Double.box(other.y$mcD$sp()))), scala.Double.unbox( Vector3$mcD$sp.this.Vector3$$num.plus( scala.Double.box(Vector3$mcD$sp.this.z()), scala.Double.box(other.z$mcD$sp()))), Vector3$mcD$sp.this.Vector3$$num);
That's scalac -optimize -Xprint:jvm
output. Now there are even subclasses for each specialized type, so that you can initialize a Vector3
without boxing, but as long as Numeric
is not specialized, you can't go further.
Well... you can write your own Numeric
and specialize that, but, at that point, I'm not sure what you are gaining by making the class parameterized in first place.
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