重载方法优先级

发布于 2024-08-22 02:07:11 字数 655 浏览 5 评论 0原文

我有一个名为 Element 的基类。其他一些类(如 Label 和 Image)都扩展了该类。

我现在有一个具有以下方法

public class Dispatcher {
    public static AbstractPropertyEditor<Label> createEditor(Label e) {
    ...
    }

    public static AbstractPropertyEditor<Element> createEditor(Element e) {
    ...
    }
}

的调度类:如果现在我有一个 Label 实例(扩展 Element)并且我想将其传递给 createEditor(),为什么是最通用的方法(第二个)打电话?调用最具体的方法(createEditor(Label e))不是很正常吗?

我绝对需要带有 Element-param 的方法,以便“捕获”所有那些 a) 实现 Element 但在此调度类中没有自己的特定方法的类。

我正在使用 Java 6,如何“修复”这?

编辑:好吧,我不得不承认这根本与泛型无关。但这是我第一次遇到它的地方。

谢谢和问候

I have a base-class called Element. Some other classes (like Label and Image) both extend this class.

I now have a dispatching class having the following methods:

public class Dispatcher {
    public static AbstractPropertyEditor<Label> createEditor(Label e) {
    ...
    }

    public static AbstractPropertyEditor<Element> createEditor(Element e) {
    ...
    }
}

If now I have an instance of Label (which extends Element) and I want to pass it to createEditor(), why is the most generic method (the second one) called? Wouldn't it be normal that the most specific method (createEditor(Label e)) is called?

I absolutely need the method with the Element-param in order to "catch" all those classes that a) implement Element but do not have their own specific method in this dispatching class..

I'm using Java 6, how to "fix" this?

Edit: Okay, I have to admit it's not at all about generics. But that's where I encountered it the first time.

thanks and regards

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

百思不得你姐 2024-08-29 02:07:11

为什么不:

  • 创建提供默认 createEditor() 实现的 Element 抽象类,
  • 使 Label 覆盖 createEditor()< /代码>。

因此,您不需要静态实用程序,并且可以实现您的目标。

如果您需要 Element 成为一个接口,那么:

  • createEditor() 定义为 Element 的方法
  • 定义一个 EditorFactory接口
  • 提供 DefaultEditorFactoryListEditorFactory
  • Element 的实现者中使用适当的工厂:

    公共编辑器createEditor() {
         editorFactory.createEditor(this);
    }
    

具体的 EditorFactory 在初始化期间或通过某种依赖注入进行实例化。


根据您的具体问题 - 这取决于您在那里编译的类型。如果您调用 createEditor(obj) ,它将取决于它是 Element obj = .. 还是 Label obj = ..

Why don't you:

  • make Element abstract class that provides a default createEditor() implementation
  • make Label override the createEditor().

Thus you won't need the static utilities and will achieve your goal.

If you need Element to be an interface, then:

  • define createEditor() as methods of Element
  • define a EditorFactory interface
  • provide DefaultEditorFactory and ListEditorFactory
  • use the appropriate factories in the implementors of Element:

    public Editor createEditor() {
         editorFactory.createEditor(this);
    }
    

where the concrete EditorFactory is instantiated either during initialization or via some sort of dependecy-injection.


As per your concrete question - it depends on what type you have compiled there. If you call createEditor(obj) it will depend whether it's Element obj = .. or Label obj = ..

浅笑轻吟梦一曲 2024-08-29 02:07:11

这实际上与泛型无关,而与方法重载有关。在Java中,调用的方法签名是在编译时确定的,而不是在运行时确定的,因此必须在运行时检查和转换。

因此,将其替换

 Element label = getLabel();
 AbstractPropertyEditor<?> editor = createEditor(label);   

 Element label = getLabel();
 AbtractPropertyEditor<?> editor;
 if(label instanceof Label) {
      editor = createEditor((Label) label);
 } else {
      editor = createEditor(label);
 }

:解决此问题的另一种(更标准/更好)方法是让 createEditor(Element) 方法检查类型并使用强制转换调用子类型的正确重载方法。但是,如果您对声明的方法执行此操作,您的返回参数将会出现问题。

This really has little to do with generics, and everything to do with method overloading. In Java, the method signature called is determined at compile time, not at runtime, so you have to check and cast at runtime.

So replace this:

 Element label = getLabel();
 AbstractPropertyEditor<?> editor = createEditor(label);   

With this:

 Element label = getLabel();
 AbtractPropertyEditor<?> editor;
 if(label instanceof Label) {
      editor = createEditor((Label) label);
 } else {
      editor = createEditor(label);
 }

The other (more standard/better) way to fix this is to have the createEditor(Element) method check the type and call with a cast the correct overloaded method for subtypes. However, you will have an issue with your return parameters if you do that on the methods as declared.

秉烛思 2024-08-29 02:07:11

来自 Java 语言规范

当调用方法时(第 15.12 节),
实际参数的数量(以及任何
显式类型参数)和
参数的编译时类型
在编译时使用
确定方法的签名
将被调用(§15.12.2)。如果
要调用的方法是
实例方法,实际的方法
被调用将在运行时确定
time
,使用动态方法查找
(§15.12.4)。

From the Java Language Specification:

When a method is invoked (§15.12), the
number of actual arguments (and any
explicit type arguments) and the
compile-time types of the arguments
are used, at compile time, to
determine the signature of the method
that will be invoked (§15.12.2). If
the method that is to be invoked is an
instance method, the actual method to
be invoked will be determined at run
time
, using dynamic method lookup
(§15.12.4).

冰葑 2024-08-29 02:07:11

因为你可能正在做:

Element element = new Label();

它是由编译器决定的。

Since you are probably doing :

Element element = new Label();

It is determined by the compiler.

二智少女 2024-08-29 02:07:11

这是重载方法的示例。
即使运行时的实际对象是标签而不是元素,
选择要调用的重载方法(换句话说,
方法)不是在运行时动态决定的。引用类型(而不是对象类型)决定调用哪个重载方法!

因此

public class Car {    
}

public class Toyota extends Car {    
}

public class MyCar {

    public void run(Car c) {
        System.out.println("Run any Car");
    }

    public void run(Toyota t) {
        System.out.println("Run Toyota Car");
    }

    public static void main(String[] args) {
        MyCar myCar = new MyCar();

        Car c1 = new Car();
        myCar.run(c1); // Output: Run any Car

        Toyota c2 = new Toyota();
        myCar.run(c2); // Output: Run Toyota Car

        Car c3 = new Toyota();
        myCar.run(c3); // Output: Run any Car    
    }
}

,在您的情况下,

Element obj1 = new Label();
Dispatcher.createEditor(obj); // Method with Element argument is called 
                              // as you are passing Element 

Label obj2 = new Label();
Dispatcher.createEditor(obj); // Method with Label argument is called 
                              // as you are passing Label

另一方面,重写的方法调用发生在运行时,并且它取决于对象类型(换句话说,堆上实际实例的类型)

This is an example of overloaded methods.
Even though the actual object at runtime is a Label and not an Element, the
choice of which overloaded method to call (in other words, the signature of the
method) is NOT dynamically decided at runtime. The reference type (not the object type) determines which overloaded method is invoked!

Example

public class Car {    
}

public class Toyota extends Car {    
}

public class MyCar {

    public void run(Car c) {
        System.out.println("Run any Car");
    }

    public void run(Toyota t) {
        System.out.println("Run Toyota Car");
    }

    public static void main(String[] args) {
        MyCar myCar = new MyCar();

        Car c1 = new Car();
        myCar.run(c1); // Output: Run any Car

        Toyota c2 = new Toyota();
        myCar.run(c2); // Output: Run Toyota Car

        Car c3 = new Toyota();
        myCar.run(c3); // Output: Run any Car    
    }
}

So, in your case

Element obj1 = new Label();
Dispatcher.createEditor(obj); // Method with Element argument is called 
                              // as you are passing Element 

Label obj2 = new Label();
Dispatcher.createEditor(obj); // Method with Label argument is called 
                              // as you are passing Label

On other note, overridden method invocation happens at run time and it depends on Object type (in other words, the type of the actual instance on the heap)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文