Scala技术疑问:抽象类伴生对象合法性与ev参数指代
Scala类型类相关问题解答
代码场景
Arithmetic.scala 文件内容
package Arithmetic // The Arithmetic typeclass which implements various arithmetic operations on custom datatypes abstract class Arithmetic[T <: Data] { implicit def cast(t: T): ArithmeticOps[T] } abstract class ArithmeticOps[T <: Data](self: T) { def *(t: T): T def mac(m1: T, m2: T): T // Returns (m1 * m2 + self) def +(t: T): T ... } object Arithmetic { implicit object UIntArithmetic extends Arithmetic[UInt] { override implicit def cast(self: UInt) = new ArithmeticOps(self) { ... } implicit object SIntArithmetic extends Arithmetic[SInt] { override implicit def cast(self: SInt) = new ArithmeticOps(self) { ... } }
另一个Scala文件内容
import Arithmetic._ class PE[T <: Data](inputType: T, ...)(implicit ev: Arithmetic[T]) extends Module { import ev._ ... }
技术疑问解答
1. 抽象类(如示例中的Arithmetic)是否可以拥有伴生对象?
可以。在Scala中,任何类(包括抽象类、特质、case类等)都可以拥有伴生对象。伴生对象与对应类必须同名且定义在同一源文件中,二者可互相访问私有成员。示例里的Arithmetic抽象类搭配同名伴生对象是完全合法的用法,这类伴生对象通常用来存放该类型类的具体实现实例(比如示例中的UIntArithmetic和SIntArithmetic)。
2. 当使用import Arithmetic._时,隐式参数ev指代的是伴生对象还是抽象类?
ev指代的是伴生对象中定义的、继承自Arithmetic[T]的隐式实例,也就是示例里的UIntArithmetic或SIntArithmetic,而非抽象类本身。
具体逻辑:
import Arithmetic._会将伴生对象Arithmetic内部的所有成员导入当前作用域,其中就包含UIntArithmetic和SIntArithmetic这两个隐式对象——它们是Arithmetic[UInt]和Arithmetic[SInt]的具体实现。- 当实例化
PE[UInt]时,Scala会自动在当前作用域中寻找符合Arithmetic[UInt]类型的隐式值,也就是UIntArithmetic,并将其绑定到隐式参数ev上;实例化PE[SInt]时则会绑定SIntArithmetic。 - 抽象类
Arithmetic[T]只是一个类型模板,本身无法被实例化,ev的类型是Arithmetic[T],但实际传入的是它的子类实例(来自伴生对象的隐式对象)。
内容的提问来源于stack exchange,提问作者xlgforever
相关产品推荐
相关产品推荐

