英文:
Is it possible to make methods non-virtual in Java?
问题
在Java中,所有非静态方法默认都是虚方法,类似于C++中的虚函数。要达到您期望的输出,可以将父类的methodA和methodB方法标记为final,这样它们就不能被子类重写。这将防止子类在调用这些方法时执行它们自己的实现。以下是修改后的代码:
public class ParentClass {
public final void methodA() {
System.out.println("This is Parent A Method");
whoAmI();
}
public final void methodB() {
System.out.println("This is Parent B Method and I am Calling Method A");
whoAmI();
methodA();
}
}
public class ChildClass extends ParentClass{
@Override
public void methodA() {
System.out.println("This is Child A Method and I am Calling Parents Method A");
whoAmI();
super.methodA();
}
@Override
public void methodB() {
System.out.println("This is Child B Method and I am Calling Parents Method B");
whoAmI();
super.methodB();
}
}
然后,您可以运行以下代码以获得期望的输出:
ChildClass c = new ChildClass();
c.methodB();
这将产生如下输出:
This is Child B Method and I am Calling Parents Method B
This is Parent B Method and I am Calling Method A
This is Parent A Method
英文:
i am newbie in java and i usually used c++ i just wondering this code works
public class ParentClass {
public void methodA() {
System.out.println("This is Parent A Method");
whoAmI();
}
public void methodB() {
System.out.println("This is Parent B Method and I am Calling Method A");
whoAmI();
methodA();
}
}
public class ChildClass extends ParentClass{
@Override
public void methodA() {
System.out.println("This is Child A Method and I am Calling Parents Method A");
whoAmI();
super.methodA();
}
@Override
public void methodB() {
System.out.println("This is Child B Method and I am Calling Parents Method B");
whoAmI();
super.methodB();
}
}
ChildClass c = new ChildClass();
c.methodB();
and I expected output like this
This is Child B Method and I am Calling Parents Method B
This is Parent B Method and I am Calling Method A
This is Parent A Method
but was
This is Child B Method and I am Calling Parents Method B
This is Parent B Method and I am Calling Method A
This is Child A Method and I am Calling Parents Method A
This is Parent A Method
so i realized that in java all non-static methods are by default virtual functions like virtual keyword in c++.
is there any way to make output like this?
This is Child B Method and I am Calling Parents Method B
This is Parent B Method and I am Calling Method A
This is Parent A Method
答案1
得分: 1
你可以将 ParentClass 的 methodA 的实现包装在一个单独的私有方法中:
public class ParentClass {
public void methodA() {
interMethodA();
}
private void interMethodA() {
System.out.println("This is Parent A Method");
whoAmI();
}
public void methodB() {
System.out.println("This is Parent B Method and I am Calling Method A");
whoAmI();
interMethodA();
}
}
而 ChildClass 保持不变。
英文:
You can wrap the methodA's impl of ParentClass in a seperate private method:
public class ParentClass {
public void methodA() {
interMethodA();
}
private void interMethodA() {
System.out.println("This is Parent A Method");
whoAmI();
}
public void methodB() {
System.out.println("This is Parent B Method and I am Calling Method A");
whoAmI();
interMethodA();
}
}
And the ChildClass remains the same.
答案2
得分: 1
代码 - 如所示 - 由于方法 whoAmI() 未定义而无法编译。通过删除对此方法的调用,我能够复制输出。
据我理解,您希望确保在 Parent 中的 methodA 从 Parent 中的 methodB 中被调用。由于在 Java 中使用了 动态分派 来确定调用哪个实际实现,我们必须强制 methodA 不能被覆盖。正如 @MarquisofLorne 所指出的,C++ 也使用了动态分派,如果在 Parent 中将 methodA 定义为 virtual。
为了确保动态分派始终调用 Parent 的 methodA,我想到了两种常见的方法:将 methodA 声明为 final 和将 methodA 声明为 private。
方法一:将 Parent 中的 methodA 声明为 final
选择这种方法时,Child 无法重新定义 methodA,即如果不从 Child 中删除 methodA,则代码将导致编译时错误。
方法二:将 Parent 中的 methodA 声明为 private
这种方法类似于第一种方法,但允许您在 Child 中保留 methodA,尽管必须删除 @Override 注解,因为私有方法无法被覆盖。
英文:
The code - as is - does not compile since method whoAmI() is undefined. By removing the calls to this method, I was able to reproduce the output.
From what I understand, you want to ensure that methodA in Parent is called from methodB in Parent. Since dynamic dispatching is used in Jjava to determine which actual implementation is called, we have to enforce that methodA cannot be overridden. As @MarquisofLorne pointed out, C++ uses dynamic dispatch aswell, if methodA is defined as virtual in Parent.
To enforce that dynamic dispatch always results in a call to Parent's methodA, there are two general approaches that come to my mind: declaring methodA as final and declaring methodA as private.
Approach one: declare methodA in Parent as final
When going down this route, Child cannot re-define methodA, i.e. the code would result in a compile-time error if methodA is not removed from Child.
Approach two: declare methodA in Parent as private
This approach is similar to the first approach, but allows you to retain methodA in Child, albeit the @Override-annotation must be removed since private methods cannot be overridden.
答案3
得分: 0
这是Child B方法,我正在调用Parent方法B
这是Parent方法B,我正在调用方法A
这是Child A方法,我正在调用Parent方法A
这是Parent方法A
英文:
You got:
This is Child B Method and I am Calling Parents Method B
This is Parent B Method and I am Calling Method A
This is Child A Method and I am Calling Parents Method A
This is Parent A Method
Instead of
This is Child B Method and I am Calling Parents Method B
This is Parent B Method and I am Calling Method A
This is Parent A Method
Simply Bacause, In Java calling methodA() or this.methodA() in your methodB() of ParentClass calls the method off of the calling object or instance, Yet the instance is an instanceof ChildClass. Java treats methodA() and this.methodA() as same. The this keyword in Java actually refers to the "currently running instance of the object you're using". Meaning, the overridding methodA() of ChildClass will be called instead of methodA() of ParentClass.
Here is a suggestion, to get the expected output, simply apply modifications on the overridding methodA() of ChildClass by commenting out the printing line.
Otherwise reference this for more details.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论