2015-04-02 1 views
0

J'ai ce cas d'utilisation que je ne peux pas résoudre. J'ai pensé à un environnement pour la programmation de passage de message. Il y a deux concepts principaux, choses et environnement: Les choses sont comme le monde réel Les choses peuvent être passives ou actives et elles peuvent envoyer et recevoir des messages. L'environnement permet la communication entre les choses. je suis venu avec cette solution:Scala class check at runtime

/**** **** Thing.scala/

abstract class Thing(environment : Environment){ 
    val uniqueName : String 
    require(environment != null) 
} 

/**** **** ActiveThing.scala/

trait ActiveThing extends Thing { 
    environment.register(this) 
    type inputType 
    type outputType 
    def receiveMessage(message : Message[inputType]) : outputType 
    def canReceiveMessage(subject : String) : Boolean 
}  

/**** **** Environment.scala/

trait Environment { 
    private var _passiveThings = List[PassiveThing]() 
    private var _activeThings = List[ActiveThing]() 

    def activeThings = _activeThings.toSeq 
    def passiveThings = _passiveThings.toSeq 
    def register(p : PassiveThing) = _passiveThings +:= p 
    def register(a : ActiveThing) = _activeThings +:= a 
    def unicastRequest[T,K](from : String, message : Message[T], to : String) : K 
} 

/**** **** Message.scala/

case class Message[T](subject : String, body : T) 

Mais lorsque je tente de mettre en œuvre effectivement:

/**** **** EchoActiveThing.scala/

class EchoActiveThing(implicit inj: Injector) extends Thing()(inj) with ActiveThing { 
    type inputType = String 
    type outputType = String 
    val uniqueName : String = "Echo" 
    def receiveMessage(message : Message[inputType]) : outputType = { 
    message.body 
    } 
    def canReceiveMessage(subject : String) : Boolean = { 
    true 
    } 
} 

/**** **** BasicEnvironment.scala/

class BasicEnvironment extends Environment { 
    def unicastRequest[T,K](from : String, message : Message[T], to : String) : K = { 
    activeThings.filter{ x => 
     x.inputType == T && 
     x.outputType == K && 
     x.canReceiveMessage(message) && 
     activeThings.contains(to.uniqueName) 
    } 
    } 
} 

Mais il ne compile pas. Je pense que je n'aborde pas le problème de la bonne façon! Merci

Répondre

1

x.inputType est une projection de type, pas une variable. Il ne peut pas être comparé avec == et c'est pourquoi le code ne compile pas. Pour comparer les types à l'exécution, vous pouvez utiliser TypeTag[T]

case class Holder[T](t: T) 

def areEqualTypes[A, B](a: Holder[A], b: Holder[B]) 
         (implicit tagA: TypeTag[A], tagB: TypeTag[B]) = { 
    tagA == tagB 
} 

val (h1, h2, h3) = (Holder("Foo"), Holder("Bar"), Holder(5)) 
println(areEqualTypes(h1, h1)) //true 
println(areEqualTypes(h1, h2)) //true 
println(areEqualTypes(h1, h3)) //false 

Dans l'exemple des balises de type sont implicitement passés à côté des paramètres de la fonction. Cette fois, vous pouvez utiliser == car tagA et tagB sont des instances de TypeTag[A] et TypeTag[B] classes.