Java动态绑定

发布于 2024-07-14 21:55:55 字数 1710 浏览 12 评论 0原文

我正在准备考试,发现了一个让我完全迷失的示例问题。 对于下面的代码,找到输出是什么:

class Moe {
    public void print(Moe p) {
        System.out.println("Moe 1\n");
    }
}
class Larry extends Moe {
    public void print(Moe p) {
        System.out.println("Larry 1\n");
    }
    public void print(Larry l) {
        System.out.println("Larry 2\n");
    }
}
class Curly extends Larry {
    public void print(Moe p) {
        System.out.println("Curly 1\n");
    }
    public void print(Larry l) {
        System.out.println("Curly 2\n");
    }
    public void print(Curly b) {
        System.out.println("Curly 3\n");
    }
}
public class Overloading_Final_Exam {
    public static void main (String [] args) {
        Larry stooge1 = new Curly();
        Moe stooge2 = new Larry();
        Moe stooge3 = new Curly();
        Curly stooge4 = new Curly();
        Larry stooge5 = new Larry();
        stooge1.print(new Moe()); 
        ((Curly)stooge1).print(new Larry()); 
        ((Larry)stooge2).print(new Moe()); 
        stooge2.print(new Curly()); 
        stooge3.print(new Curly()); 
        stooge3.print(new Moe()); 
        stooge3.print(new Larry()); 
        ((Curly)stooge3).print(new Larry()); 
        ((Curly)stooge3).print(new Curly()); 
        stooge4.print(new Curly()); 
        stooge4.print(new Moe()); 
        stooge4.print(new Larry()); 
        stooge5.print(new Curly()); 
        stooge5.print(new Larry()); 
        stooge5.print(new Moe()); 
    }
}

我心里有我的想法,但是当我运行java时,我得到了完全不同的东西:

Curly 1
Curly 2
Larry 1
Larry 1
Curly 1
Curly 1
Curly 1
Curly 2
Curly 3
Curly 3
Curly 1
Curly 2
Larry 2
Larry 2
Larry 1

前几个是好的,但后来我真的不明白。 有人对这个问题有很好的解释吗?

谢谢

I am practicing for an exam, and found a sample problem that gets me totally lost.
For the following code, find what the output is:

class Moe {
    public void print(Moe p) {
        System.out.println("Moe 1\n");
    }
}
class Larry extends Moe {
    public void print(Moe p) {
        System.out.println("Larry 1\n");
    }
    public void print(Larry l) {
        System.out.println("Larry 2\n");
    }
}
class Curly extends Larry {
    public void print(Moe p) {
        System.out.println("Curly 1\n");
    }
    public void print(Larry l) {
        System.out.println("Curly 2\n");
    }
    public void print(Curly b) {
        System.out.println("Curly 3\n");
    }
}
public class Overloading_Final_Exam {
    public static void main (String [] args) {
        Larry stooge1 = new Curly();
        Moe stooge2 = new Larry();
        Moe stooge3 = new Curly();
        Curly stooge4 = new Curly();
        Larry stooge5 = new Larry();
        stooge1.print(new Moe()); 
        ((Curly)stooge1).print(new Larry()); 
        ((Larry)stooge2).print(new Moe()); 
        stooge2.print(new Curly()); 
        stooge3.print(new Curly()); 
        stooge3.print(new Moe()); 
        stooge3.print(new Larry()); 
        ((Curly)stooge3).print(new Larry()); 
        ((Curly)stooge3).print(new Curly()); 
        stooge4.print(new Curly()); 
        stooge4.print(new Moe()); 
        stooge4.print(new Larry()); 
        stooge5.print(new Curly()); 
        stooge5.print(new Larry()); 
        stooge5.print(new Moe()); 
    }
}

I had my ideas in mind, but then when I ran the java, I got something totally different:

Curly 1
Curly 2
Larry 1
Larry 1
Curly 1
Curly 1
Curly 1
Curly 2
Curly 3
Curly 3
Curly 1
Curly 2
Larry 2
Larry 2
Larry 1

The first few ones are OK, but then I really don't understand.
Anyone has a good explanation for this problem?

Thanks

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

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

发布评论

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

评论(3

沉睡月亮 2024-07-21 21:55:55

我会从画一幅画开始......

Moe - print(Moe)
 |
Larry - print(Moe), print(Larry)
 |
Curly - print(Moe), print(Larry), print(Curly)

然后我会跟踪变量:

  • Larry - stooge1 -> 卷毛
  • 莫伊 - stooge2 -> 拉里·
  • 莫 (Larry Moe) - 傀儡3 -> 卷毛
  • 卷毛 - stooge4 -> 卷毛
  • 拉里 - stooge5 -> 拉里

  • stooge1.print(new Moe())

    • 傀儡1 -> Curly 称之为 Curly.print(Moe)
  • ((Curly)stooge1).print(new Larry());

    • 傀儡1 -> Curly 如此调用 Curly.print(new Larry())
  • ((Larry)stooge2).print(new Moe());

    • 傀儡2 -> Larry 如此调用 Larry.print(new Moe());
  • stooge2.print(new Curly());
    好吧,这就是事情变得有点棘手的地方(抱歉我之前在这里停止了一个)

    • stooge2 被声明为 Moe。 因此,当编译器考虑调用什么时,它将调用 print(Moe) 方法。 然后在运行时它知道 stooge2 是 Larry,因此它调用 Larry.print(Moe) 方法。

等等...

如果一直遵循这一点对您来说不成功,请告诉我。

(更新以澄清下一个)

所以一般规则是:

  • 编译器查看变量类型来决定调用什么方法。
  • 运行时查看变量指向的实际类来决定从哪里获取方法。

所以当你有:

Moe stooge2 = new Larry();
stooge2.print(new Moe());

编译器说:

  • Larry 可以被分配给 stooge2 吗? (是的,因为 Larry 是 Moe 的子类)
  • Moe 有 print(Moe) 方法吗? (是的)

运行时说:

  • 我应该在此对象上调用 print(Moe) 方法... stooge2
  • stooge2 指向 Larry。
  • 我将调用 Larry 类中的 print(Moe) 方法。

一旦你完成了所有这些工作,尝试摆脱一些方法,看看这会如何改变事情。

I would start by drawing a picture...

Moe - print(Moe)
 |
Larry - print(Moe), print(Larry)
 |
Curly - print(Moe), print(Larry), print(Curly)

Then I would keep track of the variables:

  • Larry - stooge1 -> Curly
  • Moe - stooge2 -> Larry
  • Moe - stooge3 -> Curly
  • Curly - stooge4 -> Curly
  • Larry - stooge5 -> Larry

  • stooge1.print(new Moe())

    • stooge1 -> Curly so calls Curly.print(Moe)
  • ((Curly)stooge1).print(new Larry());

    • stooge1 -> Curly so calls Curly.print(new Larry())
  • ((Larry)stooge2).print(new Moe());

    • stooge2 -> Larry so calls Larry.print(new Moe());
  • stooge2.print(new Curly());
    Ok, this is where it gets a bit trickier (sorry I stopped one before here)

    • stooge2 is declared to be a Moe. So when the compiler is looking at what to call it is going to call the print(Moe) method. Then at runtime it knows that stooge2 is a Larry so it calls the Larry.print(Moe) method.

etc...

Let me know if following that all the way through doesn't work out for you.

(updated to clarify the next one)

So the general rule is:

  • the compiler looks at the variable type to decide what method to call.
  • the runtime looks at the actual class that the variable is point at to decide where to get the method from.

So when you have:

Moe stooge2 = new Larry();
stooge2.print(new Moe());

the compiler says:

  • can Larry be assigned to stooge2? (yes as Larry is a subclass of Moe)
  • does Moe have a print(Moe) method? (yes)

the runtime says:

  • I am supposed to call the print(Moe) method on this here object... stooge2
  • stooge2 is point at a Larry.
  • I'll call the print(Moe) method in the Larry class.

Once you have worked all that out try getting rid of some of the methods and see how that changes things.

救星 2024-07-21 21:55:55

实际上,这个问题并不像看起来那么简单,因为Java既是静态绑定的,也是动态绑定的。 在了解从本练习中获得的所有结果之前,您必须先了解每种方法的应用场合。

TofuBeer提到的一般规则仅在动态绑定情况下才是正确的。 在静态绑定中,决策仅在编译时做出。

您的示例混合了动态绑定(当方法被重写时)和静态绑定(当方法被重载时)。

请查看此问题了解更多详细信息。

Actually, this problem is not as simple as it seems, since Java is both static and dynamically bound. You have to understand where each is applied before you will understand all the results you are getting from this exercise.

The General rule mentioned by TofuBeer is only correct in the dynamic binding case. In static binding, decisions are only made at compile time.

Your example mixes the dynamic binding (when methods are overridden) and static binding (when methods are overloaded).

Take a look at this question for more details.

旧故 2024-07-21 21:55:55

提示是在查看对象时忽略左侧的值。 相反,在声明期间查看右侧的值,这是对象的实际值。

A hint is to disregard the value on the left when looking at objects. Instead, look at the value of the right during the declaration, this is the actual value of the object.

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