Scala 中的类型参数化 [英] Type parameterization in Scala

查看:48
本文介绍了Scala 中的类型参数化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我现在正在学习 Scala,我正在尝试创建一个抽象向量类,其向量空间为 3(x、y、z 坐标).我正在尝试将其中两个向量与以下代码相加:

<预><代码>包数学类 Vector3[T](ax:T,ay:T,az:T) {def x = ax定义 y = 是定义 z = z覆盖 def toString = "<"+x+", "+y+", "+z+">"def add(that: Vector3[T]) = new Vector3(x+that.x, y+that.y, z+that.z)}

问题是我不断收到此错误:

<块引用>

错误:类型不匹配;
发现:T
需要:String
def添加(即:Vector3[T])=新Vector3(x+that.x, y+that.y,z+that.z)

我已经尝试注释掉上面的toString"方法,但这似乎没有任何效果.谁能告诉我我做错了什么?

解决方案

使用 Scala 2.8,您可以编写:

case class Vector3[T: Numeric](val x: T, val y: T, val z: T) {覆盖 def toString = "(%s, %s, %s)" 格式 (x, y, z)def add(that: Vector3[T]) = new Vector3(加(x,那个.x),加上(y, that.y),加(z,那个.z))private def plus(x: T, y: T) = 隐式[Numeric[T]] plus (x, y)}

让我解释一下.首先,T: Numeric 是一个上下文绑定,它隐式地为您的类提供了一个 Numeric[T] 实例.

Numeric[T] trait 提供对数字类型的操作,

trait Numeric[T] extends Ordering[T] {def plus(x: T, y: T): T定义减去(x:T,y:T):T定义时间(x:T,y:T):T定义否定(x:T):T//其他操作省略}

表达式 implicitly[Numeric[T]] 检索此隐式上下文,以便您可以对具体参数 x、y 和 z 执行诸如 plus 之类的操作,如上面的私有方法所示.

您现在可以构造和添加 Vector3 的不同实例,例如使用 Int's 和 Double':

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

旁注:可以使用隐式转换将值转换为 Numeric[T].Ops 实例,这样可以改为编写以下内容:

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

我故意选择不使用这些隐式转换,因为它们(可能)通过创建临时包装器对象而导致一些性能损失.实际的性能影响取决于 JVM(例如,它在多大程度上支持逃逸分析以避免实际在堆上分配对象).使用上下文绑定和隐式避免了这种潜在的开销......以一些冗长为代价.

So I'm learning 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'm trying to add two of these vectors together 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 = "<"+x+", "+y+", "+z+">"
  def add(that: Vector3[T]) = new Vector3(x+that.x, y+that.y, z+that.z)
}

The problem is I keep getting this error:

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

I've tried commenting out the "toString" method above, but that doesn't seem to have any effect. Can anyone tell me what I'm doing wrong?

解决方案

Using Scala 2.8, you could 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 bound that implicitly provides a Numeric[T] instance to your class.

The Numeric[T] trait provides operations on 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]] retrieves this implicit context such that you can perform the operations such as plus on your concrete arguments x, y and z, as illustrated in the private method above.

You can now construct and add different instantiations of Vector3 such as with Int's and Double's:

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)

Side-note: It's possible to use implicit conversions to convert values to Numeric[T].Ops instances such that the following could be written instead:

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

I've deliberately chosen not to use these implicit conversions since they (may) incur some performance penalty by creating temporary wrapper objects. Actual performance impact depends on the JVM (e.g., to which extent its supports escape analysis to avoid actual object allocation on heap). Using a context bound and implicitly avoids this potential overhead ... at the cost of some verbosity.

这篇关于Scala 中的类型参数化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆