2015年3月18日 星期三

Scala package object

不算前言
一般來說再package層級只能放class, object, trait 這些標準的定義, 可是當你有一些更小層級ex method, type, val 等等, 要放到package層級讓大家都可以使用時候, 是無法獨立一個檔案出來放, 這時候就需要scala 2.8 feature - package object

今天我遇到的問題是說
我有個case class 要定義alias name
比如說
我要定義
台灣人 class 他只有名稱
 case class TWPerson(name:String)  

然後又定義日本人 也剛好他只有名稱
一個方式是我再重複一次case class定義 好比
 case class TWPerson(name:String)  
 case class JPPerson(name:String)  

我是不打算這樣定義兩次一樣結構的class只有名稱不一樣
因為一旦fields 變多的話, 看起來就很冗長
比如
 case class TWPerson(name:String,  
                   year: String,  
                   birthday:String,  
                   father:String,  
                   mother:String,  
                   brother:String,  
                   sister:String,  
                   grandfather:String)  
 case class JPPerson(name:String,  
                   year: String,  
                   birthday:String,  
                   father:String,  
                   mother:String,  
                   brother:String,  
                   sister:String,  
                   grandfather:String)  

看吧, 如果剛好有22個fields, 就更醜了
當然你也可以說直接拿TWPersion 來new JPPersion
但語意上就會不對

scala 有type可以去alias class
但是你無法直接定義 type 在package層級
比如說
 case class TWPerson(name:String,  
                   year: String,  
                   birthday:String,  
                   father:String,  
                   mother:String,  
                   brother:String,  
                   sister:String,  
                   grandfather:String)  
 type JPPersion = TWPerson 
 //compiler error 


這時候會有error產生
因為package層級只能放標準的class, object, trait

這時候就得靠package object來幫忙了
在scala 2.8 開始有的package object
是說你可以在package下訂唯一一個的paclage.scala
比如說
在檔案路徑world/country/Person.scala 下定義
 // in file world/country/Person.scala   
 package world.country  
 case class TWPerson(name:String,  
                   year: String,  
                   birthday:String,  
                   father:String,  
                   mother:String,  
                   brother:String,  
                   sister:String,  
                   grandfather:String)  


然後我要定義type JPPerson的話
我就在檔案路徑world/country/package.scala 下定義
 // in file world/country/package.scala  
 package world  
 package object country {  
  type JPPersion = TWPersion  
 }  


這樣type JPPersion就算是TWPersion 的alias
可以給同樣package: world.country 下其他class使用

語意上來說package object 跟你定義一般的object一樣
只是說他多了個package keyword
任何在package object { } 內的東西
都可以像class 一般 import 進來直接使用

package object可以定義任何東西
method, variable, definition, implicit, type 等等
甚至可以繼承其他class, trait等等

官方的解釋文章可參考
http://www.scala-lang.org/docu/files/packageobjects/packageobjects.html

以上


沒有留言:

張貼留言