2012-07-12 17 views
8

Me explico ;-)Scala contaminación caso objeto

ambas clases siguientes están en com.company.foo paquete

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 

El problema aquí es que ADMIN es ambigua, ya que no hay separación con el espacio de nombres objetos del caso Parece que solo puede haber un objeto de caso con nombre único por paquete.

Supongo que podría nombrar objetos de casos basados ​​en la función a la mailADMIN, roleADMIN y más. ¿O debería crear Enumeramientos adecuados y olvidarme de los objetos del caso? O tomar otro enfoque?

+1

En este caso, parece que usar las enumeraciones sería una buena idea ya que puede especificar 'RoleGroup.Admin' contra' MailSender.Admin' sin preocuparse por la contaminación del espacio de nombres. – adelbertc

+0

sí, parece ser el camino a seguir, solo tratando de ver cuáles son las opciones. Quizás los objetos de mayúsculas y minúsculas estén destinados a ser utilizados solo en el ámbito local, o donde no exista posibilidad de colisión de nombres. – virtualeyes

Respuesta

13

que podría hacer algo como:

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

y lo mismo para MailSender. Luego, en situaciones en las que solo está utilizando uno, puede hacer import MailSender._ o viceversa, pero cuando utiliza ambos se refiere a ellos como RoleGroup.ADMIN, etc.

Si desea tomar este enfoque o usar Enum depende principalmente de cómo tienes la intención de usarlos. En este enfoque, cada "enum" es un tipo, mientras que con Enums cada enum es un valor. El primero funciona mejor para la coincidencia de patrones, ya que el compilador puede verificar si sus coincidencias son exhaustivas; esta última es mejor (IMO) para trabajar con la serialización.

+0

+1 enfermo, buena solución, eso debería hacer el truco – virtualeyes

+0

hace el truco, la contaminación ha desaparecido ;-) ¡gracias! – virtualeyes

+0

sí, pero el único comentario es que a menudo quiere que el rasgo se defina en el mismo nivel que el objeto, por lo que se define una relación de acompañante adecuada. En este ejemplo, realmente no importa, pero podría ser útil si extiende la funcionalidad de los tipos. –

8

No necesita enumeraciones aquí, tanto como probablemente en cualquier otro lado. Todo lo que necesitas es un espacio de nombres adecuado. Me parece que el enfoque objeto acompañante a ser la más beneficiosa:

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 
} 

Usando esta manera será mucho recordarle enumeraciones de Java, a la vez que le proporciona puntos fuertes de Scala:

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

Atención: que en la solución de Dan, el tipo de roleGroup sería RoleGroup.RoleGroup, que se siente un poco antinatural. También tenga en cuenta que los nombres en mayúsculas violan las convenciones de estilo de Scala y de ejemplos anteriores puede ver un poco por qué.

+0

+1, veo, así que mueve el rasgo fuera del objeto complementario, tiene sentido. – virtualeyes

+0

en el objeto de solución de Dan no era un objeto complementario, este (objeto) se convierte en compañero justo después de mover el rasgo fuera de él. – aeracode