Classe de cas Scala constructeur privé mais méthode d'application publique
si j'ai la classe de cas suivante avec un constructeur privé et que je ne peux pas accéder à la méthode apply dans l'objet compagnon.
case class Meter private (m: Int)
val m = Meter(10) // constructor Meter in class Meter cannot be accessed...
y a-t-il un moyen d'utiliser une classe de cas avec un constructeur privé mais de garder la méthode apply-generated dans le public compagnon?
je suis conscient qu'il n'y a pas de différence (dans mon exemple) entre les deux options:
val m1 = new Meter(10)
val m2 = Meter(10)
mais je veux interdire la première option.
-- edit --
étonnamment les œuvres suivantes (mais n'est pas vraiment ce que je veux):
val x = Meter
val m3 = x(10) // m3 : Meter = Meter(10)
3 réponses
Voici la technique pour avoir un privé constructeur et un méthode d'application publique .
trait Meter {
def m: Int
}
object Meter {
def apply(m: Int): Meter = { MeterImpl(m) }
private case class MeterImpl(m: Int) extends Meter { println(m) }
}
object Application extends App {
val m1 = new Meter(10) // Forbidden
val m2 = Meter(10)
}
informations générales privé et protégé-constructeur-en-scala
il est possible avec quelques trucs implicites:
// first case
case class Meter[T] private (m: T)(implicit ev: T =:= Int)
object Meter {
def apply(m: Int) = new Meter(m + 5)
}
a créé un autre constructeur (et appliquer la méthode signature) mais garantit que le paramètre peut être seulement Int
.
et après que vous avez classe de cas avec les caractéristiques de classe de cas (avec correspondance de modèle, hashcode & égale ) exclure constructeur par défaut:
scala> val m = Meter(10)
m: Metter[Int] = Meter(15)
scala> val m = new Meter(10)
<console>:9: error: constructor Meter in class Meter cannot be accessed in object $iw
val m = new Meter(10)
OU avec le type de marquage (implémentation naïve):
trait Private
case class Meter private (m: Integer with Private)
object Meter {
def apply(m: Int) = new Meter((m + 5).asInstanceOf[Integer with Private])
}
Il fonctionne comme prévu:
val x = new Meter(10)
<console>:11: error: constructor Meter in class Meter cannot be accessed in object $iw
new Meter(10)
^
val x = Meter(10)
x: Meter = Meter(15)
quelques problèmes possibles avec les types primitifs et les étiquettes de type décrites ici
il semble que le comportement demandé (constructeur privé mais public .apply
) puisse être la façon dont Scala 2.12 les implémente.
je suis venu à cela de l'angle opposé - comme un constructeur de classe de cas privé aussi bloquer la méthode .apply
. Raisons ici: https://github.com/akauppi/case-class-gym
intéressant, comment les cas d'utilisation diffèrent.