2017-07-13 1 views
0

Les paramètres implicites dans un constructeur de classe se comportent-ils comme des paramètres normaux de sorte que s'ils sont référencés quelque part dans cette classe, ils deviennent automatiquement des champs?Les paramètres implicites du constructeur de classe scala sont des champs?

Si oui, comment éviter que, dans ce cas:

class Triangle[@specialized T, V[_]](p1:V[T],p2:V[T],p3:V[T])(implicit ev: Addable[V[T]]){ 
    def someFuncThatUsesAddable(): Any = ??? 
} 

Si je dois créer un grand nombre de ces triangles, chaque instance contiendra référence à ajoutable résultant de l'utilisation accrue de la mémoire.

+0

Si trop de références à un seul objet deviennent vraiment un problème, vous avez de plus gros problèmes à vous faire. – wheaties

+0

@wheaties, Ce n'est pas ce dont il s'agit. Chaque instance de Triangle reçoit un champ supplémentaire 'ev'. C'est ce que je veux éviter. – Rulli

+2

@Rulli bien sûr, un champ sera créé, comment l'objet pourrait-il être utilisé plus tard quand c'est nécessaire si vous ne le stockez pas dans un champ? – puhlen

Répondre

0

Question intéressante. Je ne savais pas et j'ai décidé de vérifier. Je vois un champ est créé pour chaque paramètre implicite:

import scala.reflect.runtime.{universe => ru} 
class X 
class A() 
class B(val i: Int) 
class C(val i: Int)(implicit x: X) 

object Xc extends App { 
    implicit val x = new X() 

    def getTypeTag[T: ru.TypeTag](obj: T) = ru.typeTag[T] 

    def allDecls(d: ru.MemberScope) = d.mkString("[", ",", "]") 

    def printTypeInfo(typeA: ru.Type) = 
     println(s"type ${typeA.typeSymbol} has ${typeA.members.size} 
       members. Declarations: " + allDecls(typeA.decls)) 

     printTypeInfo(getTypeTag(new A()).tpe) 
     printTypeInfo(getTypeTag(new B(1)).tpe) 
     printTypeInfo(getTypeTag(new C(1)).tpe) 
    } 
} 

La sortie:

type class A has 22 members. Declarations: [def <init>: <?>] 
type class B has 24 members. Declarations: [val i: <?>,private[this] val i: <?>,def <init>: <?>] 
type class C has 25 members. Declarations: [val i: <?>,private[this] val i: <?>,implicit private[this] val x: <?>,def <init>: <?>] 
+0

Ouais, je suppose que Triangle lui-même doit utiliser un modèle typeclass pour se débarrasser de ces champs. Avoir un trait mettant en œuvre tout le comportement de Triangle, puis fournir une implémentation pour une classe simple particulière contenant seulement trois points de celui-ci. – Rulli

0

Oui, bien sûr, il n'y aurait pas d'autre façon de le faire (comme @puhlen souligné). Comme alternative, vous pouvez déplacer ev à des méthodes qui utilisent:

class Triangle[@specialized T, V[_]](p1:V[T],p2:V[T],p3:V[T]) { 
    def someFuncThatUsesAddable(implicit ev: Addable[V[T]]): Any = ??? 
} 

mais notez que cela change la sémantique: il faut que la Addable être portée à la méthode site d'appel, pas lorsque vous créez le triangle.

En note, je ne m'attendrais pas @specialized à être utile du tout quand T par lui-même n'est pas utilisé n'importe où.