【问题标题】:Scala: Enforce compile error on type alias mismatchScala:在类型别名不匹配时强制编译错误
【发布时间】:2014-12-30 03:10:06
【问题描述】:

在分配共享相同底层类型的不同类型别名时,有没有办法获得编译时错误(或至少是警告)?

换句话说,假设我有这个代码:

type Address = String
type City = String

def foo(x:Address) = ...

如果我这样做了,我想得到一个编译时错误/警告:

val city: City = "Dublin"
foo(city)

据我所知,编译器允许这样做是因为它们是相同的底层类型。

【问题讨论】:

    标签: scala settings type-alias


    【解决方案1】:

    据我所知,对于类型别名,不可能获得这种“类型安全”。但是,有一种替代类型别名可用于您想要的类型:Value Classes。基本上,值类可以在不分配新对象的情况下为您提供类型。请注意,对于类型别名,值类存在一些限制。

    引用 scala 文档:

    正确性

    值类的另一个用例是在没有运行时分配开销的情况下获得数据类型的类型安全。例如,表示距离的数据类型片段可能如下所示:

      class Meter(val value: Double) extends AnyVal {
        def +(m: Meter): Meter = new Meter(value + m.value)
      }
    

    添加两个距离的代码,如

      val x = new Meter(3.4)
      val y = new Meter(4.3)
      val z = x + y
    

    实际上不会分配任何 Meter 实例,而只会在运行时使用原始双精度数。

    【讨论】:

    • 我可以制作价值案例类吗?我有点不喜欢新的关键字用法
    • 您可以定义值案例类。顺便说一句:您可以省略new-keyword 的原因是(生成的)伴生对象的apply-方法,因此您不一定需要定义一个案例类来摆脱关键字。
    • 是的,我知道,我只是不想为所有类型别名定义自己的同伴,它又长又枯燥^_^
    【解决方案2】:

    没有。至少,在不修改编译器的情况下(可能可以使用编译器插件,甚至是宏),如果你做了这个改变,那么很多流行的库(包括标准库)和标准代码示例无法编译。

    您可能喜欢使用值类,如@Kulu 的回答中所述。或者,Scalaz Tagged Types 在更多情况下避免开销(例如,将它们放入集合中,或使用 subst 安全地向上转换使用标记类型的泛型类型)。

    【讨论】:

      猜你喜欢
      • 2010-12-21
      • 1970-01-01
      • 1970-01-01
      • 2012-02-16
      • 1970-01-01
      • 1970-01-01
      • 2021-11-05
      • 1970-01-01
      • 2017-10-17
      相关资源
      最近更新 更多