隐式视图失效问题排查:是否由implicit def导致?
解决Scala隐式语法扩展的问题
让我们一步步拆解你的问题,先搞定核心的a.getNum调用失败,再澄清你对隐式转换的误解。
1. 核心问题:忘记导入隐式类
你的StoresNumericOps隐式类定义在StoresNumericSyntax对象里,但你没有导入这个对象的成员,所以ANumber实例根本看不到getNum方法!这是最直接的原因。
只要在代码使用前加上导入语句:
import StoresNumericSyntax._
a.getNum就能正常工作了——你的aNumberStoresNumeric隐式实例定义其实是正确的。
2. 澄清你对隐式视图的误解
你第3点尝试获取ANumber[Int] => StoresNumeric[ANumber[Int], Int]类型的隐式值失败,是因为你定义的aNumberStoresNumeric根本不是这种类型的隐式转换:
- 你的
implicit def aNumberStoresNumeric[T: Numeric]返回的是StoresNumeric[ANumber[T], T]类型的实例,它是一个隐式证据,用来证明ANumber[T]可以提供T类型的数值,而不是把ANumber[T]转换成StoresNumeric的函数。 - 你的语法类
StoresNumericOps根本不需要A => B的隐式视图,它需要的是StoresNumeric[A, T]的隐式实例,来调用getNum方法。
3. 修正后的完整可运行代码
这里是调整后的完整代码:
abstract class StoresNumeric[A, T: Numeric] { def getNum(self: A): T } object StoresNumericSyntax { implicit class StoresNumericOps[A, T: Numeric](value: A) { def getNum(implicit sn: StoresNumeric[A, T]): T = sn.getNum(value) } } case class ANumber[T: Numeric]( num: T ) implicit def aNumberStoresNumeric[T: Numeric]: StoresNumeric[ANumber[T], T] = new StoresNumeric[ANumber[T], T] { def getNum(self: ANumber[T]): T = self.num } // 关键:导入隐式类以扩展ANumber的方法 import StoresNumericSyntax._ val a = ANumber[Int](3) // 现在可以正常运行 println(a.getNum) // 输出3 // 验证隐式证据存在(你第2点的代码是对的) println(implicitly[StoresNumeric[ANumber[Int], Int]].getNum(a)) // 输出3
4. 额外优化:简化隐式实例写法
Scala 2.13+可以用更简洁的方式定义隐式实例,比如利用匿名函数的语法糖:
implicit def aNumberStoresNumeric[T: Numeric]: StoresNumeric[ANumber[T], T] = (self: ANumber[T]) => self.num
总结一下:你的隐式实例定义是正确的,只是漏了导入隐式类;你对“隐式视图”的理解有点偏差,你的场景不需要把ANumber转换成StoresNumeric,而是需要一个StoresNumeric的隐式证据来支持语法扩展。
内容的提问来源于stack exchange,提问作者Chris J Harris
相关产品推荐
相关产品推荐

