2012-07-12 40 views
8

讓我解釋一下;-)Scala的情況下物體污染

以下兩個類都在包com.company.foo

RoleGroup.scala 
abstract class RoleGroup 
case object ADMIN extends RoleGroup 
case object MEMBER extends RoleGroup 

MailSender.scala 
abstract class MailSender 
case object ADMIN extends MailSender 
case object STAFF extends MailSender 
case object ACCOUNTANT extends MailSender 

這裏的問題是,ADMIN是模糊的,因爲有沒有命名空間分離案件對象。似乎每個軟件包只能有一個唯一命名的案例對象。

我想我可以基於功能a la mailADMIN,roleADMIN等命名案例對象。或者我應該創建適當的枚舉並忘記case對象?或者採取其他方法?

+1

在這種情況下,它看起來像使用枚舉將是一個好主意,因爲您可以指定'RoleGroup.Admin'與'MailSender.Admin'而不必擔心命名空間污染。 – adelbertc 2012-07-12 21:08:58

+0

是的,這似乎是路要走,只是想看看有什麼選擇。也許案件對象僅用於本地範圍,或者不存在名稱衝突的機會。 – virtualeyes 2012-07-12 21:14:14

回答

13

,你可以這樣做:

object RoleGroup { 
    sealed trait RoleGroup 
    case object ADMIN extends RoleGroup 
    case object MEMBER extends Rolegroup 
} 

,類似的還有MailSender。然後,在你只使用一個情況下,你使用的時候你都稱它們爲RoleGroup.ADMIN

無論你想採取這種方法,或者使用枚舉主要取決於該怎麼辦import MailSender._或反之亦然,但你打算使用它們。在這個問題上,每個「枚舉」都是一種類型,而對於枚舉,每個枚舉都是一個值。前者更適合模式匹配,因爲編譯器可以檢查匹配是否詳盡,後者比序列化更好(IMO)。

+0

+1生病,不錯的解決方案,應該做的竅門 – virtualeyes 2012-07-12 21:19:43

+0

確實沒有伎倆,污染消失了;-)謝謝! – virtualeyes 2012-07-12 21:36:38

+0

是的不錯,只有評論是你經常想要在同一級別定義的特質作爲對象,所以定義了一個適當的伴侶關係。在這個例子中,它並不重要,但如果擴展類型的功能可能會很有用。 – 2012-07-12 23:19:01

8

這裏不需要枚舉,就像其他地方一樣。所有你需要的是適當的命名空間。我覺得這是同伴對象的方法最,這有利於:

sealed abstract class RoleGroup 
object RoleGroup { 
    case object Admin extends RoleGroup 
    case object Member extends RoleGroup 
    // also just in case 
    sealed case class SomeParameterizedGroup (
    param1: Any, 
    param2: Int 
) extends RoleGroup 
} 

使用這種方式將在很大程度上提醒您Java的枚舉的,同時還爲您提供斯卡拉的優勢:

def foo (roleGroup: RoleGroup) = 
    roleGroup match { 
    case RoleGroup.Admin => 
    case RoleGroup.SomeParameterizedGroup(param1, param2) => 
    } 

請注意在丹的解決方案中,roleGroup的類型將是RoleGroup.RoleGroup,這有點不自然。另外請注意,大寫名稱違反了Scala的風格約定,從上面的例子可以看出原因。

+0

+1,我明白了,所以移動伴侶對象外的特質是有道理的。丹的解決方案對象中的 – virtualeyes 2012-07-13 12:18:28

+0

不是伴侶對象,它(對象)在將特徵移出它之後變成伴侶。 – aeracode 2013-05-01 16:25:17