我最近在学习Scala。我想尝试使用新添加的AnyVal
特性,推导出一种创建不兼容值类型的方法,这些类型不能被意外地赋值给彼此。
我能想到的最好的方式大概是这样的:
object Measurements {
trait ValueType[T] extends Any {
def value: T
}
trait Measurement[A <: ValueType[Double]] extends Any {
def modify(fn: (Double, A) => Double, value: A): A
def +(mod: A) = modify((x: Double, y: A) => x + y.value, mod)
def -(mod: A) = modify((x: Double, y: A) => x - y.value, mod)
def *(mod: A) = modify((x: Double, y: A) => x * y.value, mod)
def /(mod: A) = modify((x: Double, y: A) => x / y.value, mod)
}
case class Frequency(value: Double) extends AnyVal
with ValueType[Double]
with Measurement[Frequency]
{
def modify(fn: (Double, Frequency) => Double, mod: Frequency)
= Frequency(fn(value, mod))
}
case class Amplitude(value: Double) extends AnyVal
with ValueType[Double]
with Measurement[Amplitude]
{
def modify(fn: (Double, Amplitude) => Double, mod: Amplitude)
= Amplitude(fn(value, mod))
}
case class Wavelength(value: Double) extends AnyVal
with ValueType[Double]
with Measurement[Wavelength]
{
def modify(fn: (Double, Wavelength) => Double, mod: Wavelength)
= Wavelength(fn(value, mod))
}
}
import Measurements._
Frequency(150) + Frequency(10) // ==> Frequency(160)
Amplitude(23.2) * Amplitude(2) // ==> Amplitude(46.4)
Amplitude(50) + Frequency(50) // ==> Compile-time Type Error
很不幸,我需要为每个实例定义唯一的modify
函数,因为无法使用通用类型A
来定义类似于A(value)
的东西。没有办法定义构造函数限制。否则,我可以在特性上定义一些共同的东西,例如:
def modify(fn: (Double, A) => Double, mod: A) = A(fn(value, mod))
我已经尝试在泛型变量上调用
apply(Double)
,但无法访问。我还尝试过创建一个工厂来简化事情,但是我无法想出比我现在所做的更为优雅的解决方案。我在C#中总是遇到相同的问题。是否有一种方法可以将依赖于不同(但相关)类的共同构造函数类型的代码因子化?