Reputation: 6254
I am new to scala
. I am learning implicit variables
. How can a pass an implicit variable to a function that calls another function that is gonna use that variable. I know this question seems stupid. Just look at the code that I have written.
class Person{
def whoAmI(implicit name: String): Unit = {
println(s"I am $name")
}
}
class NewPerson{
def whoAmI: Unit = {
val p: Person = new Person
p.whoAmI
}
}
object Main extends App {
implicit val name: String = "a Shamir"
val person: NewPerson = new NewPerson
person.whoAmI
}
This code doesn't work. But this does.
class Person{
def whoAmI(implicit name: String): Unit = {
println(s"I am $name")
}
}
class NewPerson{
implicit val name: String = "a Shamir"
def whoAmI: Unit = {
val p: Person = new Person
p.whoAmI
}
}
object Main extends App {
val person: NewPerson = new NewPerson
person.whoAmI
}
I want something like this.
class Person{
def whoAmI(implicit name: String): Unit = {
println(s"I am $name")
}
}
class NewPerson{
def whoAmI: Unit = {
val p: Person = new Person
p.whoAmI
}
}
object Main extends App {
implicit val name: String = "a Shamir"
val person: NewPerson = new NewPerson
person.whoAmI()(name)
}
Is it possible?
Upvotes: 1
Views: 3244
Reputation: 28511
First of all you should pick a more refined type for implicits, having a primitive as an implicit is not very neat. A String
or Int
implicit is ALWAYS a bad idea in production code. Now you are learning so it's good to get used to this.
So let's say we have:
case class Name(name: String)
Now it's important to understand implicit propagation and forwarding. Implicits propagate through either inheritance or higher scope, so you either extend something that has the implicit you are looking for or you import it in a higher scope.
It's also best to define implicits in the secound group of function params, like this:
def test(p1: T1, p2: T2..)(implicit ev1: E1, ev2: E2): ReturnType = {}
This is because when you call the function whoAmI
with parantheses, the compiler expects the implicit passed explicitly, which voids the very point of using implicits.
So when you write the whoAmI
lik this:
def whoAmI(implicit name: Name): Unit
And you call like this: whoAmI()
with the ()
, compiler is expecting you to pass the name manually. Implicits are "hidden", meaning that once defined they are meant to be "just there", so long as you abide scoping rules they are used to eliminate typing boilerplate.
class Person {
def whoAmI()(implicit name: Name): Unit = {
println(s"I am ${name.name}")
}
}
class NewPerson {
// Here your implicit is mising
def whoAmI()(implicit name: Name): Unit = {
val p: Person = new Person
p.whoAmI
}
}
object Main extends App {
implicit val name: Name = Name("a Shamir")
val person: NewPerson = new NewPerson
// Now you don't actually need to manually type in the implicit
person.whoAmI()
}
Upvotes: 5
Reputation: 931
You should specify, that NewPerson.whoAmI takes implicit parameter and it'll be used in Person.whoAmI
class Person {
def whoAmI(implicit name: String): Unit = {
println(s"I am $name")
}
}
class NewPerson {
def whoAmI()(implicit name: String): Unit = {
val p: Person = new Person
p.whoAmI
}
}
object Main extends App {
implicit val name: String = "a Shamir"
val person: NewPerson = new NewPerson
person.whoAmI()(name)
}
Upvotes: 1