泛型方法调用重载方法的问题

2024-04-16

我遇到了有趣的事情(在 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{

}

C# code:

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
    {

    }

}

当我写这样的东西时,我希望看到在两种情况下都打印“b”。 但是,正如您所看到的,打印的是“a”。

我读过 C# 语言规范,它说重载方法是在编译时选择的。它解释了为什么它会这样工作。

不过我没时间去查看Java语言规范。

有人可以更详细地解释发生了什么以及为什么吗?我怎样才能实现我想要的?

提前致谢!


关键是要理解泛型仅在 java 中的编译时可用。它只是编译器在编译时使用的语法糖,但在生成类文件时被丢弃。

因此,代码:

   public <T extends A> void genericPrint(T b) {
      print(b);
   }

被编译为:

   public void genericPrint(A b) {
      print(b);
   }

自从争论到print属于A型,重载版本print(A a)是解决的问题。我建议对 A 或 A 的实例使用多态调用访客模式 http://en.wikipedia.org/wiki/Visitor_pattern回调到 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);
   }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

泛型方法调用重载方法的问题 的相关文章

随机推荐