如何在 Scala 中通过 class 方法传递类型参数?
How to transfer type parameter through class methods in scala?
在我的项目中,我需要编写一个泛型 class,它在单个方法中使用其处理程序以特殊方式处理某些类型(为了清楚起见,示例中使用了数字)。
class A[T](val a:T){
def doSomething(b:T):T = a match{
case a : Int => doSomethingWithIntOrDouble(b)
case a : Double => doSomethingWithIntOrDouble(b)
case _ => b
}
def doSomethingWithIntOrDouble(b:T)(implicit ev:Numeric[T]):T =
ev.plus(a,b)
}
<console>:13: error: could not find implicit value for parameter ev: Numeric[T]
case a : Int => doSomethingWithIntOrDouble(b)
^
<console>:14: error: could not find implicit value for parameter ev: Numeric[T]
case a : Double => doSomethingWithIntOrDouble(b)
我认为发生这种情况是因为编译器选择了类型参数而不是实际类型参数。告诉我,有什么办法解决这个问题吗?
PS好吧如果我们假设答案是正确的,那么就需要重载dosomething方法来实现多态
class A[T](val a:T){
def doSomething(b:T)(implicit ev:Numeric[T]):T = ev.plus(a,b)
def doSomething(b:T):T = b
}
但是在这种情况下,另一个问题出现了。
scala> a.doSomething(2)
<console>:13: error: ambiguous reference to overloaded definition,
both method doSomething in class A of type (b: Int)Int
and method doSomething in class A of type (b: Int)(implicit ev: Numeric[Int])Int
match argument types (Int)
a.doSomething(2)
我不完全确定这是你想要的,但我希望它能有所帮助。
基本上,您需要将 T
类型是 Numeric 的证据转发给外部方法。但是,您还必须处理不存在的情况。
对于这种情况,您可以像这样为隐式参数提供默认值:
class A[T](val a: T) {
def doSomething(b: T)(implicit ev: Numeric[T] = null): T = Option(ev) match {
case Some(ev) => doSomethingWithNumeric(b)(ev)
case None => b
}
def doSomethingWithNumeric(b: T)(implicit ev: Numeric[T]): T =
ev.plus(a, b)
}
似乎有效。
(new A(10)).doSomething(100) // res: Int = 110
(new A("hey")).doSomething("world") // res: String = "world"
请注意,如果您有很多方法,也许最干净的解决方案是使 A
成为 trait 并具有两种实现方式,一种用于数字类型,另一种没有数字类型。
将两个 sub 类 的构造函数设为私有,并在要求隐式数字参数的伴随对象中为 A
创建一个 factory,如果找到它将 return 数字子类的新实例。
在我的项目中,我需要编写一个泛型 class,它在单个方法中使用其处理程序以特殊方式处理某些类型(为了清楚起见,示例中使用了数字)。
class A[T](val a:T){
def doSomething(b:T):T = a match{
case a : Int => doSomethingWithIntOrDouble(b)
case a : Double => doSomethingWithIntOrDouble(b)
case _ => b
}
def doSomethingWithIntOrDouble(b:T)(implicit ev:Numeric[T]):T =
ev.plus(a,b)
}
<console>:13: error: could not find implicit value for parameter ev: Numeric[T]
case a : Int => doSomethingWithIntOrDouble(b)
^
<console>:14: error: could not find implicit value for parameter ev: Numeric[T]
case a : Double => doSomethingWithIntOrDouble(b)
我认为发生这种情况是因为编译器选择了类型参数而不是实际类型参数。告诉我,有什么办法解决这个问题吗?
PS好吧如果我们假设答案是正确的,那么就需要重载dosomething方法来实现多态
class A[T](val a:T){
def doSomething(b:T)(implicit ev:Numeric[T]):T = ev.plus(a,b)
def doSomething(b:T):T = b
}
但是在这种情况下,另一个问题出现了。
scala> a.doSomething(2)
<console>:13: error: ambiguous reference to overloaded definition,
both method doSomething in class A of type (b: Int)Int
and method doSomething in class A of type (b: Int)(implicit ev: Numeric[Int])Int
match argument types (Int)
a.doSomething(2)
我不完全确定这是你想要的,但我希望它能有所帮助。
基本上,您需要将 T
类型是 Numeric 的证据转发给外部方法。但是,您还必须处理不存在的情况。
对于这种情况,您可以像这样为隐式参数提供默认值:
class A[T](val a: T) {
def doSomething(b: T)(implicit ev: Numeric[T] = null): T = Option(ev) match {
case Some(ev) => doSomethingWithNumeric(b)(ev)
case None => b
}
def doSomethingWithNumeric(b: T)(implicit ev: Numeric[T]): T =
ev.plus(a, b)
}
似乎有效。
(new A(10)).doSomething(100) // res: Int = 110
(new A("hey")).doSomething("world") // res: String = "world"
请注意,如果您有很多方法,也许最干净的解决方案是使 A
成为 trait 并具有两种实现方式,一种用于数字类型,另一种没有数字类型。
将两个 sub 类 的构造函数设为私有,并在要求隐式数字参数的伴随对象中为 A
创建一个 factory,如果找到它将 return 数字子类的新实例。