Ser*_*nko 4 c# java generics overloading
我遇到了有趣的事情(在Java和C#中都一样).Java代码:
public class TestStuff {
public static void main(String[] args) {
Printer p = new PrinterImpl();
p.genericPrint(new B());
}
}
class PrinterImpl implements Printer {
void print(A a) {
System.out.println("a");
}
void print(B b) {
System.out.println("b");
}
@Override
public <T extends A> void genericPrint(T b) {
print(b);
}
}
interface Printer {
public <T extends A> void genericPrint(T a);
}
class A {
}
class B extends A{
}
Run Code Online (Sandbox Code Playgroud)
C#代码:
namespace TestStuff
{
internal class Program
{
private static void Main(string[] args)
{
var printer = new Printer();
printer.GenericPrint(new B());
}
}
public class Printer
{
public void Print(A a)
{
Console.WriteLine("a");
}
public void Print(B b)
{
Console.WriteLine("b");
}
public void GenericPrint<T>(T a) where T : A
{
Print(a);
}
}
public class B : A
{
}
public class A
{
}
}
Run Code Online (Sandbox Code Playgroud)
当我写这样的东西时,我希望在这两种情况下都能看到"b".但是,正如你所看到的,它是"一个"印刷的东西.
我已经阅读了C#语言规范,它说在编译时选择了重载方法.它解释了为什么它以这种方式工作.
但是,我没有时间在Java语言规范中查看它.
有人可以更详细地解释发生了什么以及为什么?我怎么能实现我想要的?
提前致谢!
关键是要理解泛型只能在java的编译时使用.它只是编译器在编译时使用的语法糖,但在生成类文件时会丢弃.
因此,代码:
public <T extends A> void genericPrint(T b) {
print(b);
}
Run Code Online (Sandbox Code Playgroud)
编译成:
public void genericPrint(A b) {
print(b);
}
Run Code Online (Sandbox Code Playgroud)
由于参数print是A类型,因此重载版本print(A a)是已解析的版本.我建议对A或者访问者模式的实例使用多态调用来回调用于您的用例的PrinterImpl.
就像是:
interface Visitor {
void visit(A a);
void visit(B b);
}
class PrinterImpl implements Printer, Visitor {
void print(A a) {
System.out.println("a");
}
void print(B b) {
System.out.println("b");
}
public <T extends A> void genericPrint(T b) {
b.accept(this);
}
public void visit(A a) {
print(a);
}
public void visit(B b) {
print(b);
}
}
interface Printer {
public <T extends A> void genericPrint(T a);
}
class A {
public void accept(Visitor v) {
v.visit(this);
}
}
class B extends A {
public void accept(Visitor v) {
v.visit(this);
}
}
Run Code Online (Sandbox Code Playgroud)