Type parameterization in Scala

So, I'm studying Scala at the moment, and I'm trying to create an abstract vector class with a vector space of 3 (x, y, z coordinates). I am trying to add two of these vectors along with the following code:

package math class Vector3[T](ax:T,ay:T,az:T) { def x = ax def y = ay def z = az override def toString = "&lt"+x+", "+y+", "+z+"&gt" def add(that: Vector3[T]) = new Vector3(x+that.x, y+that.y, z+that.z) } 

The problem is that I keep getting this error:

error: type of discrepancy;
found: T
required: String
def add (what: Vector3 [T]) = new Vector3 (x + that.x, y + that.y, g + that.z)

I tried to comment on the toString method above, but this does not seem to have any effect. Can someone tell me what I am doing wrong?

+4
source share
4 answers

Using Scala 2.8, you can write:

 case class Vector3[T: Numeric](val x: T, val y: T, val z: T) { override def toString = "(%s, %s, %s)" format (x, y, z) def add(that: Vector3[T]) = new Vector3( plus(x, that.x), plus(y, that.y), plus(z, that.z) ) private def plus(x: T, y: T) = implicitly[Numeric[T]] plus (x, y) } 

Let me explain. First, T: Numeric is a context boundary that implicitly provides an instance of Numeric[T] for your class.

The Numeric[T] function provides operations with numeric types,

 trait Numeric[T] extends Ordering[T] { def plus(x: T, y: T): T def minus(x: T, y: T): T def times(x: T, y: T): T def negate(x: T): T // other operations omitted } 

The expression implicitly[Numeric[T]] extracts this implicit context, so you can perform operations like plus on your specific arguments x, y, and z, as shown in the private method above.

Now you can build and add various instances of Vector3 , such as Int and Double :

 scala> Vector3(1,2,3) add Vector3(4,5,6) res1: Vector3[Int] = (5, 7, 9) scala> Vector3(1.1, 2.2, 3.3) add Vector3(4.4, 5.5, 6.6) res2: Vector3[Double] = (5.5, 7.7, 9.899999999999999) 

Note: you can use implicit conversions to convert values ​​to Numeric[T].Ops instances, so instead of them you could write the following:

  def add(that: Vector3[T]) = new Vector3(x + that.x, y + that.y, z + that.z) 

I intentionally decided not to use these implicit conversions, as they (may) carry some performance limitations by creating temporary wrapper objects. The actual performance impact depends on the JVM (for example, the extent to which its support avoids analysis to avoid the actual distribution of objects on the heap). Using a bound context and implicitly avoids this potential overhead ... due to some verbosity.

+7
source

You have not restricted a parameter of type T, and therefore, the compiler returns to interpreting + as a string concatenation.

+8
source

Problem T This is a type of Any , but Any does not have a + operator. An error in a String is a small error. So you need to define a min binding to the type that does.

+6
source

Both answers from @sblundy and @Randall Schulz are true of course, but if you need more specific recommendations on how to limit T, then what about:

 class Vector3[T <% Double](ax:T,ay:T,az:T) { ... } 
+3
source

Source: https://habr.com/ru/post/1309809/


All Articles