2016-04-11 1 views
-1

Voici une structure de code:Comment se référer à une méthode paramétrée?

trait Foo[T <: Foo[_]] { 
    def makeACopy[T](attr01_p: Option[String], ...): T 
    ... 
} 

case class Bar extend Foo[Bar] { 
    def makeACopy[Bar](attr01_p: Option[String], ...): org.myapp.domain.model.Bar = copy(attr01 = attr01_p, ...) 
    ... 
} 

Maintenant, une méthode dans une autre classe a besoin de se référer à la méthode makeACopy.

class Qux(...){ 
    ... 
    private def myMethod[T <: Foo](id: Long, getter: Long => Option[T], ...): Option[T] = { 
    val b = getter(id) 
    b match { 
     case Some(bar) => bar.makeACopy[T](...) // <== It isn't right 
     case None => ... 
    } 
} 

je reçois une erreur pour le respect d'appeler la méthode makeACopy bien que je précise déjà le paramètre comme un sous-type d'IDEA Foo et Intellij ne se plaint pas de la ligne:

value makeACopy is not a member of type parameter T 

Pourquoi? Et comment le résoudre?

Aussi, je ne suis pas sûr pourquoi je dois avoir un chemin complet pour le type de données retourné de makeACopy dans Bar. Dans le cas contraire, l'EDI se plaindra de la non-concordance de type renvoyée.

+1

Vous devez être perdu dans votre '' Foo's et Bar's :) La raison pour laquelle vous devez indiquer le nom du package dans ce type de retour suggère un peu (il y a plus d'une barre). Aussi '[T <: Foo]' ne devrait pas compiler, parce que 'Foo' doit être paramétré, donc, si vous n'obtenez pas d'erreur sur cette ligne, cela suggère, il y a probablement un autre' Foo' dans la portée .. – Dima

+0

Merci pour votre contribution. Cela ne semble pas être mon cas. Je peux seulement trouver une de ces classes avec les noms. – TeeKai

+0

Quoi que ... En tout cas, 'Foo [T <: Foo]' n'est pas un code valide, peut-être que intellij est confus ou quelque chose. Vous devez le réparer avant d'aller de l'avant. – Dima

Répondre

1

vous définissez deux paramètres de type distincts nommés T, et que l'un d'entre eux comme une sous-classe de Foo:

trait Foo[T <: Foo[_]] { // defining T once 
    // that's another definition of a whole different T: 
    def makeACopy[T](attr01_p: Option[String], ...): T 
    ... 
} 

Une méthode définie au sein d'un trait (ou classe) avec un paramètre de type T ne devrait pas déclarer à nouveau T, vous voudrez probablement changer cela:

trait Foo[T <: Foo[_]] { 
    // T used as return value is the one defined in trait: 
    def makeACopy(attr01_p: Option[String], ...): T 
    ... 
} 

Ensuite, chaque fois que vous appelez/remplacer makeACopy, vous n'avez pas besoin pour spécifier le type, vous avez déjà fait lorsque vous avez créé/étendu Foo, par exemple:

case class Bar extend Foo[Bar] { 
    def makeACopy(attr01_p: Option[String], ...): Bar = copy(attr01 = attr01_p, ...) 
    ... 
}