简体   繁体   中英

Generic type in Scala

I started studying recently Scala. And I don't understand why this code is not working. Can anybody help me?

import scala.collection.mutable
import scala.collection.mutable.Map

class Bijection[T] (val v: Set[T]) {
  private var addition = 0
  private var reversed = false

  def add(i: Int)(implicit ev: T <:< Int) = {
    addition += i
  }

  def reverse(implicit ev: T <:< String) = {
    reversed = !reversed
  }
}

object Bijection {
  def apply(s: Set[String]): Bijection[String] = {
    println("Hello string")
    Bijection(s)
  }

  def apply[T](s: Set[T]): Bijection[T] = {
    println("Hello T")
    Bijection(s)
  }
}

object Main {
  def main(args: Array[String]): Unit = {
    var x = Bijection[String](Set[String]("fd", "fasf"))
  }
}

This code should print "Hello" But I get now next trace.

Error:(23, 7) double definition:
def apply(s: Set[String]): Bijection[String] at line 18 and
def apply[T](s: Set[T]): Bijection[T] at line 23
have same type after erasure: (s: scala.collection.immutable.Set)Bijection
  def apply[T](s: Set[T]): Bijection[T] = {

The JVM doesn't have reified generics , instead, it erases type parameters at runtime, even though they're stored in bytecode. The only reason it has type parameters are to check things at compile time. Because of this, your 2 apply methods will both have the signature.

def apply(s: Set): Bijection

at runtime.

Because of this, there's no way for the right apply method to be chosen.

Furthermore, you have to call the constructor inside the apply method. If you don't use new , then you'll just call the same apply method again, going into infinite recursion.

Instead, you can do something like this. If it's not a string, the implicit parameter will remain null, and you will know that it is not a String but some other T .

object Bijection {
  private def applyString(s: Set[String]): Bijection[String] = {
    println("Hello String")
    new Bijection(s)
  }
  
  private def applyT[T](s: Set[T]): Bijection[T] = {
    println("Hello T")
    new Bijection(s)
  }
  
  def apply[T](s: Set[T])(implicit ev: Set[T] =:= Set[String] = null): Bijection[T] =
    if (ev == null) applyT(s) else applyString(s).asInstanceOf[Bijection[T]]
}

You don't have to change anything else.

Scastie

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM