2013-09-30 3 views
0

J'ai un objet factory qui crée des instances de certains éléments (c'est-à-dire un type interne). J'ai aussi une opération qui fonctionne sur des éléments créés par l'usine. Voici le code:Comment forcer l'inférence de type sans utiliser de classe abstraite

class Factory { 
    class Element private [Factory] (val int:Int) 
    def create(from:Int) = new Element(from) 
} 

class OperationOnFactoryElement(val factory:Factory) { 
    def apply(element:factory.Element) = factory.create(element.int + 1) 
} 

val factory = new Factory 

val op = new OperationOnFactoryElement(factory) 

val someElement = factory.create(1) 

op(someElement) // this causes an error!! 

//<console>:13: error: type mismatch; 
// found : factory.Element 
// required: op.factory.Element 
//    op(someElement) 
//    ^

Il est clair que le compilateur attend de moi d'utiliser l'usine intégrée dans le OperationOnFactoryElement d'accepter l'opération. Cependant, si j'ai besoin de définir plus d'opérations sur cet élément, cela devient un problème car je ne peux pas, par exemple, combiner les deux opérations. Je suis venu avec cette solution:

class Factory { 
    class Element private [Factory] (val int:Int) 
    def create(from:Int) = new Element(from) 
} 

abstract class OperationOnFactoryElement { 
    val factory:Factory 
    def apply(element:factory.Element) = factory.create(element.int + 1) 
} 

val myfactory = new Factory 

val op = new OperationOnFactoryElement { 
val factory:myfactory.type = myfactory 
} 
val someElement = myfactory.create(1) 

op(someElement) // this works 

Cependant, je suis forcé de transformer mon opération en classe abstraite. Ma question est:

Existe-t-il un moyen d'obtenir le même résultat sans rendre la classe OperationOnFactoryElement abstraite?

Répondre

2

Vous pouvez utiliser Factory#Element dire apply d'attendre un Element défini avec ce changement, votre premier exemple de code dans un Factory

class OperationOnFactoryElement(val factory:Factory) { 
    def apply(element:Factory#Element) = factory.create(element.int + 1) 
} 

devrait fonctionner comme cela est.

scala> class Factory { 
    | class Element private [Factory] (val int:Int) 
    | def create(from:Int) = new Element(from) 
    | } 
defined class Factory 

scala> class OperationOnFactoryElement(val factory:Factory) { 
    | def apply(element:Factory#Element) = factory.create(element.int + 1) 
    | } 
defined class OperationOnFactoryElement 

scala> val factory = new Factory 
factory: Factory = [email protected] 

scala> val op = new OperationOnFactoryElement(factory) 
op: OperationOnFactoryElement = [email protected] 

scala> val someElement = factory.create(1) 
someElement: factory.Element = [email protected] 

scala> op(someElement) 
res0: op.factory.Element = [email protected] 

scala> someElement.int 
res1: Int = 1 

scala> res0.int 
res2: Int = 2 
Questions connexes