Closed Simn closed 5 years ago
Turns out javac
generates a generalized function in that case...
public class Main implements I<java.lang.String>
{
public static void main(String[] args)
{
I<java.lang.String> i = new Main();
i.get("foo");
}
void Main() { }
public void get(String arg) {
System.out.println(arg);
}
}
public void get(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=0, locals=2, args_size=2
0: return
LineNumberTable:
line 13: 0
public void get(java.lang.Object);
descriptor: (Ljava/lang/Object;)V
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: checkcast #8 // class java/lang/String
5: invokevirtual #9 // Method get:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 1: 0
That makes me sad.
And yes, the run-time dispatches to the generalized function:
interface I<T> {
public function get(t:T):Void;
}
class Main implements I<String> {
static public function main() {
var i:I<String> = new Main();
i.get("foo");
}
function new() { }
@:overload public function get(s:String) {
Sys.println("get(String): " + s);
}
@:overload public function get(obj:Dynamic) {
Sys.println("get(Dynamic): " + obj);
}
}
get(Dynamic): foo
That means we have to error in this case. Java does so too:
Name clash: The method get(Object) of type Main has the same erasure as get(T) of type I<T> but does not override
Alternatively, we could treat all interfaces with type parameters as if they were @:generic
. But that probably comes with its own set of issues.
Actually, this affects base-class relations too:
class Base<T> {
public function get(t:T):Void {
Sys.println("get(T): " + t);
}
}
class Main extends Base<String> {
static public function main() {
var i:Base<String> = new Main();
i.get("foo");
}
function new() { }
override public function get(s:String) {
Sys.println("get(String): " + s);
}
}
get(T): foo
The problem is this
invokeinterface
instruction:I wonder if this is supposed to use the concrete type...