为什么在Java中父类会调用子类的方法?

huangapple go评论65阅读模式
英文:

Why the parent class will call the subclass method in java?

问题

我有两个类:

public class A {
    void add(int a){
        System.out.println("A.add");
    }

    void addAll(int[] a){
        System.out.println("A.addAll");
        for(int i = 0;i < a.length;i++){
            add(a[i]);
        }
    }
}

public class B extends A{
    @Override
    void add(int a){
        System.out.println("B.add");
        super.add(a);
    }
    
    @Override
    void addAll(int[] a){
        System.out.println("B.add");
        super.addAll(a);
    }
    
    public static void main(String[] args){
        (new B()).addAll(new int[]{1,2,3,4});
    }
}

当我开始运行这个应用程序时,输出是:

B.add
A.addAll
B.add
A.add
B.add
A.add
B.add
A.add
B.add
A.add

为什么类A中的addAll函数会调用类B中的add函数,而不是调用自己的add函数?

英文:

I have two classes:

public class A {
	void add(int a){
		System.out.println(&quot;A.add&quot;);
	}

	void addAll(int[] a){
		System.out.println(&quot;A.addAll&quot;);
		for(int i = 0;i &lt; a.length;i++){
			add(a[i]);
		}
	}
}

public class B extends A{
	@Override
	void add(int a){
		System.out.println(&quot;B.add&quot;);
		super.add(a);
	}
	
	@Override
	void addAll(int[] a){
		System.out.println(&quot;B.add&quot;);
		super.addAll(a);
	}
	
	
	public static void main(String[] args){
		(new B()).addAll(new int[]{1,2,3,4});
	}
}

And when I start to run this application, the output is

B.add
A.addAll
B.add
A.add
B.add
A.add
B.add
A.add
B.add
A.add

Why the addAll function in class A will call the add function in class B rather than call its own add function?

答案1

得分: 2

我认为Derek误解了你的意思。Super确实指的是父类(A),但你可以看到在B的add函数之前有一个@override关键字。由于是B对象调用了addAll函数(new B()),A的add被B的add函数覆盖了。因此,它首先调用B的add函数,然后是A的add函数。

英文:

I think Derek has misunderstood your meant. Super indeed refers to the parent class (A), but you can see there's a @override keyword before B's add function. Since it is a B object calls addAll function (new B()), the A's add is override by B's add function. Therefore it calls B's add function first, then A's add function.

答案2

得分: 2

因为这就是多态的工作原理。任何非私有的/静态的/终态的方法都可以被重写,无论你是从类外部还是内部调用它。

在类 A 中,在 addAll() 中调用了一个非私有方法 add()。如果你在子类 B 中重写了 add() 方法,A 中的 addAll() 将会调用 B 的 add() 方法。这是非常明显的。

实际上,我认为让你困惑的是为什么会这样工作。
在 Java 中,如果你将一个方法声明为非私有和非终态的,那么你是在告诉任何子类可以改变它的行为,这就是重写的意思。如果你不希望子类改变它的行为,你可以将它声明为私有的或者终态的,或者将你的类声明为终态的。

英文:

Because that's how polymorphism works. Any non-private/static/final method can be overrided, no matter you call it from outside of the class or inside.

In class A,you call a non-private method add() in addAll(). If you override add() method in subClass B, the addAll() in A will call the B's add() method.This is quite obvious.

In fact I think what confuse you is why it work like that.
In java, if you declare a method as non-private and non-final, you are telling that any subclass can change it's behavior, that's what override means. If you don't want subclass to change it's behavior, you can either declare it as private or final or make you class final.

答案3

得分: 0

这就是动态方法调度。调用的引用是“B”,它已经覆盖了“A”的add()和addAll()方法。现在,当B的引用调用addAll()时,将调用B的版本。这里没有什么不明显的。现在,B的addAll的版本有super.addAll(),这也是直观的。有趣的是,当调用A的addAll()的主体时,它调用了“add()”。在这里,由于启动整个调用链的运行时引用是B,而且B也已经覆盖了A的“add()”,因此在A的“addAll()”主体内部调用了B的“add()”版本。动态方法调度和运行时多态性决定了这种行为,其中在调用中分派的所有方法都取决于调用变量具有的实际引用。

英文:

This is dynamic method dispatch. The calling reference is of "B" which has overridden both add() and addAll() of "A". Now, when B's reference invokes addAll(), B's version is called. Nothing not obvious here. Now B's version of addAll has super.addAll(), which also think is intuitive.
What's interesting is that when the body of A's addAll() is invoked, it has invocation to "add()". Here, since the runtime reference using which the entire call chain was started is of B and B has overridden "add()" of A as well, thus B's version of "add()" is invoked from within the "addAll()" body of A.
Dynamic method dispatch and runtime polymorphism dictates this behaviour where all methods that are dispatched in an invocation depends on the actual reference that the invoking variable has.

huangapple
  • 本文由 发表于 2020年9月23日 10:28:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/64020166.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定