Java中使用不同参数数据类型的继承和重载方法 [英] Inheritance and Overloading methods with different argument data types in Java

查看:1732
本文介绍了Java中使用不同参数数据类型的继承和重载方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我分析一个与重载和继承相关的简单java代码时,我希望收到一个重载匹配参数数据类型的输出。但它不起作用。

When I was analyzing a simple java code related with overloading and inheritance I expected to recieve an output that overloads matching the argument's data types. But it doesn't work that way.

代码:

class A {
        public int calc (double num){
            System.out.println("calc A");
            return (int)(num+1);}
    }
class B extends A{
        public int calc (long num){
            System.out.println("calc B");
            return (int)(num+2);}
    }
class C extends B{
        public int calc (int num){
            System.out.println("calc C");
            return num+3;}
    }
class D extends C{
        public int calc (float num){
            System.out.println("calc D");
            return (int)(num+4);}
    }

class Program{
        public static void main(String[] args){
            int num1=10;
            long num2 = num1;

            Object o1 = num1;
            System.out.println("num1 Type: "+o1.getClass().getName());

            Object o2 = num2;
            System.out.println("num2 Type: "+o2.getClass().getName());

            A a1=new D();
            A a2=new D();

            System.out.println("a1 Type: "+a1.getClass().getName());
            System.out.println("a2 Type: "+a2.getClass().getName());

            int result = a1.calc(num1)+a2.calc(num2);
            System.out.println("Number: "+result);
        }
    }

输出:

num1 Type: java.lang.Integer
num2 Type: java.lang.Long
a1 Type: D
a2 Type: D
calc A
calc A
Number: 22

I在这里测试代码:
ideone

I was testing the code here: ideone

推荐答案

您的主要问题似乎是为什么类型输出与正式类型不匹配。这完全是故意的,这就是使面向对象编程如此强大的原因。

Your main question seems to be about why the type outputs don't match with the formal types. This is entirely intentional, and it's what makes object oriented programming so powerful.

当在实例上调用方法时,运行时系统会查看实例的实际类型,并根据其实际类型查找要调用的方法,而不是查找其正式类型。

When a method is invoked on an instance, the runtime system looks at the actual type of the instance, and looks up the method to call based on its actual type, rather than on its formal type.

如果不是这种情况,则无法进行得到任何有用的东西。您希望能够声明一个抽象类 A ,具体类 B C 挂掉它以不同的方式实现细节。但是你也希望能够声明 A 类型的变量,而不关心它们来自哪里,以及它们是否实际上是类型B 或输入 C 。然后你可以调用属于 A 合同一部分的方法,它会做正确的事:真的是 B 将调用 B 的实现,同样适用于 C

If this weren't the case, you wouldn't be able to get anything useful done. You want to be able to declare an abstract class A, with concrete classes B and C hanging off it that implement the details in different ways. But you also want to be able to declare variables of type A, without caring where they've come from, and whether they're actually of type B or type C. You can then invoke methods that are part of the contract of A, and it'll do the right thing: something that's really a B will invoke B's implementation, and likewise for C.

至于为什么你最终调用 A calc 方法而不是 D ,这又是因为多态的工作方式。变量的正式类型是 A ;因此,当您调用 .calc()时,类型系统将:

As for why you end up invoking A's calc method rather than D's, this is again because of the way polymorphism works. The formal type of the variables is A; so when you invoke .calc(), the type system will:


  1. find类 A 中最合适的方法,以便在编译时匹配调用 ;

  2. 查看是否有在 A 和实际类型在运行时之间被覆盖;

  3. 如果有的话,调用被覆盖的版本,或 A 的版本,如果没有。

  1. find the most appropriate method in class A to match the call at compile time;
  2. see whether that has been overridden between A and the actual type at runtime;
  3. call the overridden version if there is one, or A's version if not.

但你还没有完全覆盖 calc()方法:您提供了具有不同签名的方法。所以在第1步(编译时)类型系统找到 A.calc(double);在步骤2中(在运行时),它发现它没有在类层次结构中进一步覆盖;因此,在步骤3(运行时)中,它调用 A 的版本。

But you haven't overridden the calc() method at all: you've supplied methods with different signatures. So in step 1 (at compile time) the type system finds A.calc(double); in step 2 (at runtime) it discovers that this hasn't been overridden further down the class hierarchy; in step 3 (runtime) it therefore invokes A's version.

过载在编译时基于形式类型;根据实际类型在运行时解析覆盖。

Overloads are resolved at compile time based on formal types; overrides are resolved at runtime based on actual types.

这篇关于Java中使用不同参数数据类型的继承和重载方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆