Scala 2.11中的类型化基元

时间:2015-03-28 10:36:27

标签: scala

正如我所见,StringLong这样的原始类型无法扩展,因为它们被定义为final。但这对于类型安全的方法来说是一种遗憾。在围绕的代码中字符串操作,我更喜欢键入我的数据,而不是使用String,Long,Int等:只要我使用类型安全的语言,我就像我的代码真的从头开始打字。

根据实验和as demonstrated on a very old question类型别名似乎不利于此。目前,我将使用以下内容:

case class DomainType(value: String)

代价是必须使用需要值的.value

scala 2.8之后是否还引入了其他语言功能,可以巧妙地促进类型安全的子类型原语?是否存在代理基础值的任何对象覆盖,但仍然会发生类型匹配?

3 个答案:

答案 0 :(得分:6)

我不同意你的思维方式。 Java原语无法扩展,因为它们是原语(btw String不是原语)。它们是字节代码类型的直接表示。从编译器的角度来看,扩展它们是没有意义的。

隐含值类

Scala使用 pimp my library 模式处理此问题,例如使用类RichInt。这允许在没有对象实例化(通过value classes和implicits)的情况下(主要)向现有类型添加新方法。另请查看implicit classes

implicit class DomainType(val o: String) extends AnyVal {
  def myDomainMethod: Int = o.size
}

"hello".myDomainMethod // return 5

问题,这并不允许您像对待DomainType那样限制类型。但类型类可以帮助你。

输入类

这里我们要为类型添加约束,而不继承。如this link中所述,

  

因此,类型类允许ad-hoc和retroactive多态。依赖于类型类的代码可以扩展而不需要创建适配器对象。

以下示例显示方法foo如何仅接受类型为DomainType[T]的隐式在范围内的参数。它取代了追溯多态性所需的继承。您还可以保留域类型的好处:意图很明确,呼叫类型安全,您可以添加新的域方法。

trait DomainType[T] {
  def myDomainMethod(o: T): Int
}

object DomainType {
  implicit object StringDomainType extends DomainType[String] {
    def myDomainMethod(o: String): Int = o.size
  }
}

def foo[T : DomainType](p: T): Int = {
  implicitly[DomainType[T]].myDomainMethod(p)
}

foo("hello") // return 5
foo(5) // compilation exception

案例类+暗示

如果您DomainType案例类唯一令您烦恼的事情就是致电.value,您可以随时添加一个隐含的功能。

implicit def unwrapDomainType(o: DomainType): String = o.value

当然这会降低代码的清晰度,我不会推荐它。

答案 1 :(得分:2)

对于基本类型,您可以使用值类。它们不扩展基本类型,但它们在内部由JVM基元表示,因此它们在大多数情况下避免了运行时开销。您可以找到更多信息here

答案 2 :(得分:0)

似乎标签类型形式scalaz将是一个很好的选择。

val a: Int @@ DomainType = Tag(5)

有关用法的更多信息,请查看以下优秀系列文章: http://eed3si9n.com/learning-scalaz/Tagged+type.html不幸的是,似乎必须从scalaz 7.1开始明确调用unwrap,但是使用scalaz7可以调用类似的东西:

a * 5

但根据您的需要,这可能仍然有用