管理费;拳击“;Scala中通过隐式的基元类型

管理费;拳击“;Scala中通过隐式的基元类型,scala,implicit-conversion,Scala,Implicit Conversion,假设我想要一个类似JavaDate的类。它唯一的数据成员是long,表示自1970年以来的毫秒数 仅仅制作一个新的Scala类型是否有性能优势: type PrimitiveDate = Long 然后可以使用隐式转换添加方法,就像使用RichInt对int进行转换一样。将基元类型“装箱”到富类中是否涉及任何开销(类创建)?基本上你可以有一个静态的方法 def addMonth(date: PrimitiveDate, months: Int): PrimitiveDate = date +

假设我想要一个类似Java
Date
的类。它唯一的数据成员是long,表示自1970年以来的毫秒数

仅仅制作一个新的Scala类型是否有性能优势:

type PrimitiveDate = Long
然后可以使用隐式转换添加方法,就像使用
RichInt
对int进行转换一样。将基元类型“装箱”到富类中是否涉及任何开销(类创建)?基本上你可以有一个静态的方法

def addMonth(date: PrimitiveDate, months: Int): PrimitiveDate = date + 2592000000 * months
然后让类型系统计算出当
d添加第5个月时必须应用它
显示在代码中

编辑

通过编写
type PrimitiveDate=Long
创建的别名似乎没有被scala编译器强制执行。在Scala中创建一个合适的类(包含Long)是创建强制类型的唯一方法吗

<>你认为能够为原始类型创建一个强制类型别名吗?< /p> 嗯,<强> < />强应该意味着最近的JVM实际上不必创建你的富包装器来调用<代码> AdvAuth[/Cord>]方法。 这种情况在实践中实际发生的程度显然取决于JVM决定这些方法在对象创建中添加了多少运行时热点。当不进行转义分析时,显然JVM必须在包装类的新实例中“装箱”(如您所说)长的
。它不涉及“类创建”-它将涉及“创建类的实例”。这种情况下,如果寿命短,则会立即进行GC-d,因此开销(虽然很小)为:

  • 实例的内存分配
  • GC正在初始化实例
很明显,如果您确实在编写非常低延迟的代码,并且试图最小化垃圾创建(在一个紧密的循环中),那么这些问题只会成为任何类型的问题。只有你知道情况是否如此

至于这种方法是否适合你(逃避分析对你有帮助),你必须在野外进行测试。众所周知,为这类事情编写微型基准测试非常困难


我不太喜欢将这些类型别名作为公共API的一部分的原因是scala并没有像我希望的那样严格地执行它们。例如:

type PrimitiveDate = Long
type PrimitiveSpeed = Long
type Car = String
type Meeting = String

var maxSpeeds : Map[Car, PrimitiveSpeed] = Map.empty

//OOPS - much too easy to accidentally send the wrong type
def setDate(meeting : Meeting, date : PrimitiveDate) = maxSpeeds += (meeting -> date)

在给定的示例中,您实际上并没有创建新类型,它只是先前存在的Long类型的别名

这是我经常使用的一种技术,用于处理笨拙的嵌套连接。例如,我使用别名
type Grid=Seq[Seq[Int]]
,以避免为各种参数反复指定
Seq[Seq[Int]]

您可以非常愉快地将
Long
传递给采用
PrimitiveDate
方法的方法,尽管确实有这样的优势,即代码可以更好地自文档化

如果您确实希望创建一个具有强制类型安全性和方便的模式匹配的新类型,我将使用case类:

case class PrimitiveDate(value:Long)

而且,为了方便起见,甚至可能提供隐式的Long=>PrimitiveDate转换。

在您提出这个问题11个月后,迈尔斯·萨宾发现了一种在Scala中创建的非常简单、优雅和高效的方法。与类型别名不同,类型标记是强制的。基本类型需要最少的样板文件(每个基本类型一行)来提供专门化

一年后,他又将这一点添加到了一个列表中。这个概念非常简单和简洁,如果你不想要这个优秀的库的其余部分,可以在项目中复制,而不需要添加不成形的内容


当然,你和回答你问题的人可能都知道这一点,但值得在此补充,因为这仍然是一个重要的问题。

关于“强制使用别名”的观点很好。这是我想知道的一件事。因此,在scala中无法为基元类型创建正确的类型别名?@ziggystar-不,没有。我倾向于将类型别名用于以下两件事之一:凯文在下面谈到的私人内部事务;包对象导入(即为什么
List
似乎仍然在
scala
包中)我认为迈尔斯·萨宾在提出这个问题11个月后提出了一个优雅而高效的解决方案。我想这些未绑定的新类型与前面提到的幻影类型类似,对吗?