Scala 隐式转换实现长度单位自动转换

19 阅读2分钟
object imp03 {
  class KM(var value:Double) {
    override def toString: String = s"${value} 千米"
  }
  class BN(var value:Double) {
    override def toString: String = s"${value} 百米"
  }
  class M(var value:Double) {
    override def toString: String = s"${value} 米"
  }

  // 补充隐式转换函数,把 KM -> M
  implicit def km2m(km:KM): M = { new M(km.value * 1000) }
  // 补充隐式函数,把 BN -> M
  //

  def main(args: Array[String]): Unit = {
    val km1 = new KM(2)
    val m1:M = km1
    val m2:M = new BN(2)
    println(m1)
    println(m2)
  }
}

1. 定义类

代码中定义了三个类,用来表示不同的长度单位:

scala

class KM(var value: Double) {
  override def toString: String = s"${value} 千米"
}
  • KM 表示 “千米”,构造函数接收一个 Double 类型的数值。
  • toString 方法重写,返回类似 "2.0 千米" 的字符串。

scala

class BN(var value: Double) {
  override def toString: String = s"${value} 百米"
}
  • BN 表示 “百米”,即 1 百米 = 100 米
  • 同样重写了 toString,返回类似 "2.0 百米"

scala

class M(var value: Double) {
  override def toString: String = s"${value} 米"
}
  • M 表示 “米”。
  • 重写 toString 后,返回类似 "2000.0 米"

2. 隐式转换

Scala 提供了 隐式转换implicit)机制,可以在需要某种类型时,自动将一个类型转换为另一个类型。

scala

implicit def km2m(km: KM): M = { new M(km.value * 1000) }
  • 这是一个隐式函数,用于将 KM 类型转换为 M 类型。
  • 转换公式:1 千米 = 1000 米
  • 当编译器发现需要 M 类型,但实际提供的是 KM 类型时,会自动调用这个函数进行转换。

3. 缺失的隐式转换

代码中还有一个注释:

scala

// 补充隐式函数,把 BN -> M
//
  • 这里是提示我们需要补充一个隐式函数,将 BN 类型转换为 M 类型。

  • 公式:1 百米 = 100 米

  • 如果没有这个函数,编译器在执行:

    scala

    val m2: M = new BN(2)
    

    时会报错,因为它不知道如何把 BN 转成 M


4. main 方法

scala

def main(args: Array[String]): Unit = {
  val km1 = new KM(2)
  val m1: M = km1
  val m2: M = new BN(2)
  println(m1)
  println(m2)
}
  • 创建一个 KM 对象(2 千米)。
  • 编译器自动调用 km2m 函数,将 KM 转换为 M
  • 创建一个 BN 对象(2 百米)。
  • 如果有 BN -> M 的隐式函数,会自动转换;否则报错。
  • 打印两个 M 对象的 toString

5. 运行结果(补全后)

如果我们补全:

scala

implicit def bn2m(bn: BN): M = { new M(bn.value * 100) }

运行结果:

plaintext

2000.0 
200.0 

✅ 总结

  • 这是一个演示 Scala 隐式转换 的程序。
  • 通过隐式函数,可以让不同类型的单位在需要时自动转换。
  • 隐式转换可以简化代码,让不同类型之间的运算或赋值更加自然。
  • 代码中缺失了 BN -> M 的隐式转换,需要补充才能完整运行。