Reputation: 339
HI I have a case when calling a method to use self. Now not sure the best practice to do this in Scala. I have created a example of how I'm doing it just wanted to ask is this the best way of doing so.
sealed trait Animal {
// match on self
final def speak(): Unit = {
this match {
case Cat(name) => println("spoken like a Cat named: " + name)
case Dog(name) => println("spoken like a Dog named: " + name)
case Pig(name) => println("spoken like a Pig named: " + name)
}
}
final def whoAmI(): Unit = {
this match {
case Cat(_) => println("I am a Cat")
case Dog(_) => println("I am a Dog")
case Pig(_) => println("Could be a Pig")
}
}
}
final case class Cat(name: String) extends Animal
final case class Dog(name: String) extends Animal
final case class Pig(name: String) extends Animal
Upvotes: 1
Views: 72
Reputation: 515
Yes, your use of pattern matching on this
is correct.
Since your hierarchy is sealed, you know, that there will not be any new types to account for - otherwise you should have the _ => ...
clause.
You can express your second case a bit simpler, since you dont care about the parameters, only about the type.
final def whoAmI(): Unit = {
this match {
case _:Cat => println("I am a Cat")
case _:Dog => println("I am a Dog")
case _:Pig => println("Could be a Pig")
}
}
Finally, this
always refers to the innermost type. In case of nested inner classes, you might want to use an alias, like self
:
trait Tweeter {
this: self => // reassign this into self, so it can be accessed from an inner class
Upvotes: 1
Reputation: 3964
If your requirement is only to know which sub-type is used, it can be accessed in a more straightforward manner with just this.getClass()
:
sealed trait Animal {
val name: String
final def speak(): Unit =
println(s"spoken like a ${this.getClass.getSimpleName} named: ${name}")
final def whoAmI(): Unit =
println(s"I am a ${this.getClass.getSimpleName}")
}
If all the implementing sub-types are characterized by a name
, that would be convenient to declare an abstract val name: String
, which will allow to access the field in speak()
.
For a use case like this the matchers are not the best option: for each implementing sub-type you have to add an entry in the matchers (may become difficult to maintain). I'd suggest using inheritance: if you have a behavior differentiated among the sub-types, declare an abstract method in the trait, call it from it, but its implementations should remain at sub-types level.
Upvotes: 4