8

Let me explain ;-)

both classes below are in package 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

The problem here is that ADMIN is ambiguous since there is no namespace separation with case objects. It seems there can only be one uniquely named case object per package.

I suppose I could name case objects based on function a la mailADMIN, roleADMIN and so on. Or should I just create proper Enums and forget about case objects? Or take some other approach?

4

2 に答える 2

13

you could do something like:

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

and similarly for MailSender. Then in situations where you're only using one, you can do import MailSender._ or vise versa, but when using both you refer to them as RoleGroup.ADMIN, etc.

Whether you want to take this approach or use Enums mostly depends on how you intend to use them. In this aproach, each "enum" is a type, whereas with Enums each enum is a value. The former works better for pattern matching since the compiler can check if your matches are exhaustive, the latter is better (IMO) for working with serialization.

于 2012-07-12T21:15:31.787 に答える
8

You don't need enums here, as much as probably anywhere else. All you need is proper namespacing. I find the companion object approach to be the most benefitial:

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
}

Using it this way will very much remind you of Java's enums, while also providing you with strengths of Scala:

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

Please note that in Dan's solution the type of roleGroup would be RoleGroup.RoleGroup, which kinda feels unnatural. Also note that uppercase names violate Scala's style conventions and from examples above you can kinda see why.

于 2012-07-13T09:43:45.237 に答える