Is there a way in scala to call a method belonging to a type? For example, suppose I have a trait called Constructable
that describes types than can construct a default instance of themselves. Then, I can write the following code:
trait Constructable[A] {
def construct: A
}
class Foo(x: Int) extends Constructable[Foo] {
def construct = new Foo(0)
}
def main(args: Array[String]) {
val f = new Foo(4)
println(f.construct)
}
This is ok, but what I really want is to be able to construct a default object given only the type of object. For example, suppose I want to accept a list of constructables and prepend a default object at the beginning of the list:
def prependDefault1[A <: Constructable[A]](c: List[A]): List[A] = {
val h = c.head
h.construct :: c
}
The above code works, but only if c is not empty. What I'd really like is to write something like the following:
def prependDefault2[A <: Constructable[A]](c: List[A]): List[A] = {
A.construct :: c
}
Is there any way to achieve this, possibly by changing the definition of a Constructable
so that the construct
method belongs to the "class" rather than the "instance" (to use Java terminology)?
You can't do this way, but you can do this using typeclasses:
trait Constructable[A] {
def construct: A
}
// 'case' just so it's printed nicely
case class Foo(x: Int)
// implicit vals have to be inside some object; omitting it here for clarity
implicit val fooConstructable = new Constructable[Foo] {
def construct = new Foo (0)
}
def prependDefault2[A : Constructable](c: List[A]): List[A] = {
implicitly[Constructable[A]].construct :: c
}
And then:
scala> prependDefault2(Nil: List[Foo])
res7: List[Foo] = List(Foo(0))
Some final remarks:
Implicits have to live inside an object. There are three places it can be located:
object Constructable { implicit val fooConstructable = ...
(companion object of the typeclass trait)
object Foo { implicit val fooConstructable = ...
(companion object of the class we implement typeclass for)
object SomethingElse { implicit val fooConstructable = ...
(some random unrelated object)
Only in the last case you need to use import SomethingElse._
in order to be able to use the implicit.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.