加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

在Scala中使用构造函数

发布时间:2020-12-16 10:02:54 所属栏目:安全 来源:网络整理
导读:我一直在 Scala做一些练习.我想我可能会尝试使用新添加的AnyVal特性来创建一种创建不兼容的值类型的方法,这些值不能被意外地相互分配. 我能想到的最好的是这样的: object Measurements { trait ValueType[T] extends Any { def value: T } trait Measuremen
我一直在 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

不幸的是,它要求我为每个实例唯一地定义修改函数,因为不可能用通用类型A定义类似A(值)的东西.似乎没有办法定义构造函数约束.否则我可以在特征上定义一些常见的东西,例如:

def modify(fn: (Double,mod: A) = A(fn(value,mod))

我试过在A上调用apply(Double),但是无法从泛型变量访问它.我还试着看看我是否能够建立一个至少可以简化工作的工厂,但却无法提出比我现在做的更优雅的东西.我一直遇到与C#相同的问题.

是否有某种方法可以分解出依赖于不同(但相关)类的通用构造函数类型的代码?

解决方法

我不认为这是可能的,如果不诉诸运行时反射(或可能是宏).基本上有三个问题,你已经指出了两个问题:

>特征不可能声明强制构造函数签名.
>无法调用诸如应用于A之类的方法,因为它是类型变量而不是类或对象.
>由于值类(当前)只能扩展universal traits,而不是抽象类,因此无法使用TypeTags来获取属于在扩展Measurement时实例化A的类型的类.

我能想到的最好的方法是以下方法.注意,它使用反射,如果Measurement的具体实例没有声明适当的构造函数,则可以在运行时抛出异常.

// ... as above ...

trait Measurement[A <: ValueType[Double]] extends Any { self: A =>
  def modify(fn: (Double,mod: A): A =
    this.getClass
        .getConstructor(this.getClass)
        .newInstance(fn(value,mod): java.lang.Double)

  // ... as above ...
}

case class Frequency(value: Double)
    extends AnyVal 
       with ValueType[Double] 
       with Measurement[Frequency]

// ... etc ...

Frequency(150) + Frequency(10) // ==> Frequency(160)
Amplitude(23.2) * Amplitude(2) // ==> Amplitude(46.4)
Amplitude(50) + Frequency(50)  // ==> Compile-time Type Error

自我类型注释self:A确保ValueType声明的值字段可从内部特征Measurement中访问.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读