2012-07-12 20 views
8

Pozwól mi wyjaśnić ;-)scala przypadek obiekt zanieczyszczenie

poniżej obie klasy są w pakiecie 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 

Problem polega na tym, że ADMIN jest niejednoznaczny, ponieważ nie ma separacji z nazw obiekty sprawy. Wygląda na to, że w jednym pakiecie może znajdować się tylko jeden obiekt o unikalnej nazwie.

Przypuszczam, że mógłbym nazwać obiekty sprawy na podstawie funkcji a la mailADMIN, roleADMIN i tak dalej. Czy powinienem po prostu stworzyć odpowiednie wyliczenia i zapomnieć o obiektach sprawy? Lub podjąć inne podejście?

+1

W tym przypadku wygląda na to, że użycie wyliczeń byłoby dobrym pomysłem, ponieważ można określić 'RoleGroup.Admin' zamiast' MailSender.Admin' bez martwienia się o zanieczyszczenie przestrzeni nazw. – adelbertc

+0

tak, wydaje się, że droga do celu, po prostu próbuje zobaczyć, jakie są opcje. Być może obiekty sprawy mają być używane tylko w zasięgu lokalnym lub tam, gdzie nie ma szans na kolizję nazw. – virtualeyes

Odpowiedz

13

mógłby zrobić coś takiego:

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

i podobnie dla MailSender. Wtedy, w sytuacjach, w których używasz tylko jednego, możesz wykonać import MailSender._ lub odwrotnie, ale gdy używasz obu, nazywasz je RoleGroup.ADMIN, itp.

Niezależnie od tego, czy chcesz zastosować to podejście, czy użyć. zamierzasz z nich korzystać. W tym podejściu, każde "wyliczenie" jest typem, podczas gdy z wyliczeniami każde wyliczenie jest wartością. Ten pierwszy działa lepiej w przypadku dopasowywania wzorców, ponieważ kompilator może sprawdzić, czy twoje dopasowania są wyczerpujące, drugie jest lepsze (IMO) do pracy z serializacją.

+0

+1 chory, fajne rozwiązanie, które powinno załatwić sprawę – virtualeyes

+0

rzeczywiście działa, zanieczyszczenia zniknęły ;-) dzięki! – virtualeyes

+0

Tak, ale komentarz jest taki, że często chcesz, aby cecha była zdefiniowana na tym samym poziomie co obiekt, aby zdefiniować właściwą relację towarzyszącą. W tym przykładzie nie ma to znaczenia, ale może być użyteczne, jeśli rozszerzysz funkcjonalność typów. –

8

Nie musisz tutaj wyliczać, tak jak prawdopodobnie nigdzie indziej. Wszystko, czego potrzebujesz, to właściwy obszar nazw. Uważam, że podejście obiektowe towarzysz za najbardziej 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 
} 

korzystanie z niego w ten sposób będzie bardzo przypominać o teksty stałe Javy, jednocześnie umożliwiając korzystanie z zalet Scala:

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

Uwaga że w rozwiązaniu Dana typ roleGroup będzie RoleGroup.RoleGroup, co w pewnym sensie wydaje się nienaturalne. Zwróć też uwagę, że wielkie litery naruszają konwencje stylu Scala, a z powyższych przykładów możesz zobaczyć dlaczego.

+0

+1, widzę, więc przesunięcie cechy poza obiekt towarzysza ma sens. – virtualeyes

+0

w obiekcie rozwiązania Dan nie był obiektem towarzyszącym, to (obiekt) staje się towarzyszem zaraz po przeniesieniu cechy poza nim. – aeracode

Powiązane problemy