假设我想参加像Java这样的课程 Date. 。它唯一的数据成员是一个长期代表自1970年以来毫秒的长期。

仅制作新的Scala类型的任何性能好处是否会有所收益:

type PrimitiveDate = Long

然后,您可以通过使用隐式转换来添加方法,就像使用INT一样 RichInt. 。原始类型的“拳击”是否涉及任何开销(班级创建)?基本上您只能有静态方法

def addMonth(date: PrimitiveDate, months: Int): PrimitiveDate = date + 2592000000 * months

并让类型系统弄清楚它必须在 d addMonth 5出现在您的代码中。

编辑

看来您通过写作创建的别名 type PrimitiveDate = Long 不受Scala编译器强制执行。是创建一个适当的类,封闭长长的唯一方法来创建Scala中的强制类型吗?

您认为能够为原始类型创建强制性类型的别名如何有用?

有帮助吗?

解决方案

出色地, 逃生分析 应该意味着最新的JVM实际上不必创建您的 丰富的包装纸 为了致电 addMonth 方法。

这在多大程度上 实际上是在实践中发生的 显然将取决于运行时多少 热点 JVM决定这些方法正在添加在对象创建中。当没有发生逃生分析时,显然,JVM必须“盒子”(您说) Long 在包装器类的新实例中。它不涉及“类创建” - 它将涉及“创建类的实例”。此实例,短暂的寿命将立即为GC-D,因此开销(小)为:

  • 实例的内存分配
  • gc-ing实例

显然,如果您肯定要编写非常低的延迟代码,那么这些问题显然才是任何问题,您试图最大程度地减少垃圾的创造(在紧密的循环中)。只有您知道是否就是这种情况。

至于该方法是否适合您(逃避分析得到帮助),您必须在野外进行测试。众所周知,微基准很难为这种事情编写。


我不太喜欢这些类型别名的原因 成为公共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)

其他提示

您实际上并没有在给定的示例中创建一种新类型,它只是预先存在的长期类型的别名。

这是我经常使用的技术来处理笨拙的嵌套连接。例如,我别名 type Grid = Seq[Seq[Int]] 避免必须指定 Seq[Seq[Int]] 一遍又一遍地以获取各种参数。

你可以很高兴地通过 Long 采用一种方法 PrimitiveDate 方法,尽管你 有一个优势,即代码更好地记载。

如果您确实想创建具有强制类型安全和方便的图案匹配的新类型,我将使用一个案例类:

case class PrimitiveDate(value:Long)

而且,即使为方便起见,甚至可能提供一个隐性的长=>原始的转换。

问这个问题11个月后,迈尔斯·萨宾(Miles Sabin)发现了一种非常简单,优雅和表现的创建方式 未包装的新型 在Scala中。与类型的别名不同,类型标签被强制执行。原始类型需要最小的样板(每条原始线)才能提供专业化。

一年后,他添加了一个 更加抛光和健壮的版本 这是 无形. 。这个概念简单明了,可以在项目中复制,而不会添加无形状的话,如果您不希望其余的出色的库。

当然,您和回答您问题的人都可能知道这一点,但是值得在这里添加,因为这仍然是一个重要的问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top