斯卡拉案件对象污染

时间:2012-07-12 21:01:25

标签: scala enums namespaces

让我解释一下; - )

以下两个类都在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是不明确的,因为没有与case对象的命名空间分离。似乎每个包只能有一个唯一命名的case对象。

我想我可以根据函数la mailADMIN,roleADMIN等命名case对象。或者我应该创建适当的枚举并忘记案例对象?或采取其他方法?

2 个答案:

答案 0 :(得分:13)

你可以做点什么:

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

,同样适用于MailSender。然后,在您只使用一个的情况下,您可以import MailSender._或反之亦然,但在使用它们时,请将它们称为RoleGroup.ADMIN等。

是否要采用此方法或使用枚举主要取决于您打算如何使用它们。在这个方法中,每个“枚举”都是一种类型,而对于枚举,每个枚举都是一个值。前者适用于模式匹配,因为编译器可以检查您的匹配是否详尽,后者更适合(IMO)进行序列化。

答案 1 :(得分: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的枚举,同时还为您提供Scala的优势:

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

请注意,在Dan的解决方案中,roleGroup的类型为RoleGroup.RoleGroup,这有点不自然。另请注意,大写名称违反了Scala的样式约定,从上面的示例中可以看出原因。