scala - questions - video question tags
Cómo proporcionar un valor predeterminado para los parámetros implícitos a nivel de clase (2)
Estoy tratando de definir una clase con algunos métodos tomando un parámetro implícito:
object Greetings {
def say(name: String)(implicit greetings: String): String = greetings + " " +name
}
Yo uso esta clase de otra clase
implicit val greetings = "hello" //> greetings : java.lang.String = hello
Greetings.say("loic") //> res0: String = hello loic
Greetings.say("loic")("hi") //> res1: String = hi loic
Mi problema es que solo funciona si defino el valor implícito fuera de mi objeto Greetings. Me gustaría poder proporcionar métodos con parámetros implícitos, con un valor predeterminado dentro de mi clase, para facilitar el uso de mi API (como la API de colección de Scala).
Así que me gustaría hacer esto, pero no funciona (no se encuentra el valor implícito):
object Greetings {
implicit val greetings = "hello"
def say(name: String)(implicit greetings: String): String = greetings + " " +name
}
y entonces
Greetings.say("loic")
Greetings.say("loic")("hi")
Sé que puedo definir un valor predeterminado con (implicit greetings: String = "hello")
pero me gustaría hacerlo a nivel de clase, para evitar que se repita si hay muchos métodos.
Supongo que me estoy perdiendo algo porque vi que CanBuildFrom
está definido dentro de la clase List
, por ejemplo.
Es una mala idea usar un tipo tan general como String
en un implícito. La razón principal es que la búsqueda implícita se basa únicamente en el tipo, así que, ¿qué sucede si alguien más define otro valor implícito de tipo String? Usted podría terminar con un conflicto. Por lo tanto, debe definir su propio tipo específico para su propio propósito (una envoltura simple alrededor de String).
Otra razón es que al buscar valores implícitos, el compilador buscará (entre otros lugares) en el objeto complementario (si existe) del tipo de valor implícito. Puede ver fácilmente lo útil que es, ya que el objeto complementario es el lugar natural para poner un valor implícito predeterminado (como en su caso). Pero si el valor implícito es de un tipo que no posee (como String
) simplemente no puede escribir un objeto complementario para él, mientras que con su propio tipo de envoltorio no hay problema.
OK, basta de verborrea, aquí está cómo puedes hacerlo:
case class Greetings( value: String ) {
override def toString = value
}
object Greetings {
// this implicit is just so that we don''t have to manually wrap
// the string when explicitly passing a Greetings instance
implicit def stringToGreetings( value: String ) = Greetings( value )
// default implicit Greetings value
implicit val greetings: Greetings ="hello"
def say(name: String)(implicit greetings: Greetings): String = greetings + " " +name
}
Greetings.say("loic")
Greetings.say("loic")("hi")
He encontrado una solución:
class Greetings(implicit val greetings: String = "hello") {
def say(name: String): String = greetings + " " + name
}
De este modo, puedo tener un valor predeterminado y anularlo si quiero:
new Greetings().say("loic") //> res0: String = hello loic
implicit val greetings = "hi" //> greetings : java.lang.String = hi
new Greetings().say("loic") //> res1: String = hi loic
new Greetings()("coucou").say("loic") //> res2: String = coucou loic
Nota: new Greetings()("coucou")
está funcionando, no new Greetings("coucou")
, debido a una extraña sintaxis explicada here .