2017-07-28 29 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