Why overloading polymorphic methods with different upper bounds does not compile in Scala

Why the following does not compile in Scala:

class A
class B

object X {
  def f[Q <: A](q: Q): Q = q
  def f[Q <: B](q: Q): Q = q
}

with error message

<console>:16: error: method f is defined twice
  conflicting symbols both originated in file '<console>'
         def f[Q <: B](q: Q): Q = q

As I understand it, after deleting a type, you def f[Q <: A](q: Q): Qshould replace it with the upper boundary: def f(q: A): Anyand the second one is overloaded, frespectively. Therefore, they should be distinguishable after erasing the styles.

So why is Scala complaining?

+6
source share
4 answers

Resubmit the comment as an answer to improve visibility.

I found this old post about what seems to be the same problem: http://www.scala-lang.org/old/node/4625.html

, Scala, , , (Scala -only) . .

, - - , SO, , Dotty - Skala?;) - .

+3

@chengpohi, ( - ) :

trait A
trait B

implicit class RichA[Q <: A](q: Q){ def f = q }

implicit class RichB[Q <: B](q: Q){ def f = q }

scala> (new A{}).f
res0: A = $anon$1@39c1fe0b

scala> (new B{}).f
res1: B = $anon$1@20011bf

, , , Scala Java ( ), Java- Scala . ( ) - , , JVM invokestatic :

, . . 9 , .

invokestatic , , ( ). . , , methodname .

, , Q <: A - Q , , , @chengpohi, ( - runtime-type ).


Haskell, , ( ), , .

P.S. , Haskell ( ) , Java.

+5

Scala, Java :

def f[Q <: A](q: Q): Q = q
def f[Q <: B](q: Q): Q = q

Java:

public <Q extend A> Q f(q: Q) { return q;}
public <Q extend B> Q f(q: Q) { return q;}

, erasure , , C - A B, , , f apply.

, , :

Scala trait:

trait A
trait B

class C extends A with B

C A B. f .

In Java - , interface . . :

interface C {
}
interface D {
}
static class A implements D, C {
}
public <Q extends C> Q f(Q q) {
    return q;
}
public <Q extends D> Q f(Q q) {
    return q;
}
new TestTmp().f(new A()) // Ambiguous call in here.
+2

, Java. a b. Scala - , .

public class A {}
public class B {}

public class Test {
    public <Q extends A> Q f(Q q) {
        System.out.println("with A");
        return q;
    }

    public <Q extends B> Q f(Q q) {
        System.out.println("with B");
        return q;
    }

    public static void main(String[] args) {
        final A a = new A() {};
        final B b = new B() {};

        final Test test = new Test();

        test.f(a);
        test.f(b);
    }
}
+2

Source: https://habr.com/ru/post/1016318/


All Articles