2017-07-28 23 views
2

Initialy我们有这样的代码解构会导致未来的错误吗?

class Person(firstName: String, lastName: String) 

val (firstName, lastName) = person 

有人交换领域

class Person(lastName: String, firstName: String) 

val (firstName, lastName) = person 

编译器是幸福的!

+2

看起来两个参数都有相同的类型字符串,如果你在字符串中传递th参数,编译器不检查是Fname还是Lname,它只检查params类型。所以问题不在于编译器。 –

回答

5

编译器无法知道你交换了字段的顺序,因为分析没有查找参数名称。只要typer类型检查,一切都很好。你可以做的是额外的类型:

case class FirstName(name: String) 
case class LastName(name: String) 

class Person(firstName: FirstName, lastName: LastName) 

现在交换的类型会导致编译时错误。

如果你不想allocationing其他对象的额外开销,看看shapeless tagged types

import [email protected]@ 

trait FirstNameTag 
trait LastNameTag 

type FirstName = String @@ FirstNameTag 
type LastName = String @@ LastNameTag 

case class Person(fn: FirstName, ln: LastName) 

现在:

import shapeless.tag 

val firstName: FirstName = tag[FirstNameTag][String]("yuv") 
val lastName: LastName = tag[LastName][String]("itz") 

val person = Person(firstName, lastName) 

或@Ren指出使用value classes

case class FirstName(name: String) extends AnyVal 
case class LastName(name: String) extends AnyVal 
+1

还有“扩展AnyVal”选项以避免开销 - http://docs.scala-lang.org/overviews/core/value-classes.html – Ren

+0

@Ren绝对!已添加到答案 –

+0

@Ren值类可以工作,但它们在您创建额外对象之前可以对它们执行的操作中受到限制。最糟糕的部分是他们会默默初始化,当你认为他们不是时,会给你一个表现。如果他们避免这些问题,我不知道标记类型,但是如果他们这样做,他们是比AnyVal更好的选择 – puhlen