Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的静态和动态绑定_Java_Oop_Binding_Polymorphism_Dynamic Binding - Fatal编程技术网

Java中的静态和动态绑定

Java中的静态和动态绑定,java,oop,binding,polymorphism,dynamic-binding,Java,Oop,Binding,Polymorphism,Dynamic Binding,请有人给我解释一下最后6行输出是如何打印出来的。我知道由于静电装订,前三行印刷得很恰当 IpodPlayer player2 = null; if(ipl instance of IpodPlayer) player2 = (IpodPlayer)ipl; 我不知道为什么第5行会给出输出,因为它是Ipod类型,没有任何歌曲方法,但仍然会打印输出。 代码如下: package myferrari; import mycar.*; class IPOD { void PlayM

请有人给我解释一下最后6行输出是如何打印出来的。我知道由于静电装订,前三行印刷得很恰当

IpodPlayer player2 = null;
if(ipl instance of IpodPlayer)
    player2 = (IpodPlayer)ipl;
我不知道为什么第5行会给出输出,因为它是Ipod类型,没有任何歌曲方法,但仍然会打印输出。 代码如下:

package myferrari;

import mycar.*;

class IPOD
{
    void PlayMusic(Music m)
    {
        System.out.println("Music from Ipod");
    }
}

class IpodPlayer extends IPOD
{
    void PlayMusic(Music m)
    {
        System.out.println("Music from IpodPlayer");
    }

    void PlayMusic(Song m)
    {
        System.out.println("Song from IpodPlayer");
    }
}

class Music{}
class Song extends Music{}

public class Main  {

    public static void main(String [] args)
    {
        IPOD ipod = new IPOD();
        IpodPlayer iplayer = new IpodPlayer();
        IPOD ipl = new IpodPlayer();

        Music m = new Music();
        Song s = new Song();
        Music sm = new Song();

        iplayer.PlayMusic(m);
        iplayer.PlayMusic(s);
        iplayer.PlayMusic(sm);  // static binding refers to the reference type

        ipod.PlayMusic(m);      
        ipod.PlayMusic(s);
        ipod.PlayMusic(sm);

        ipl.PlayMusic(m);
        ipl.PlayMusic(s);
        ipl.PlayMusic(sm);

    }
}
输出如下:

来自IpodPlayer的音乐 来自IpodPlayer的歌曲 来自IpodPlayer的音乐 来自Ipod的音乐 来自Ipod的音乐 来自Ipod的音乐 来自IpodPlayer的音乐 来自IpodPlayer的音乐 来自IpodPlayer的音乐
进行打印的类有一个方法,该方法将对象作为音乐类,而不是Song的子类

为了做你想做的事,你必须做以下事情:

void PlayMusic(Music m){
  if(m instance of Song){
    System.out.println("Song from Ipod");
  } else
    System.out.println("Music from Ipod");
}
由于您将ipl声明为超级类IPOD并将其实例化为IPodPlayer,因此除非您检查其类型并适当地强制转换,否则它的行为与IPOD相同

IpodPlayer player2 = null;
if(ipl instance of IpodPlayer)
    player2 = (IpodPlayer)ipl;
但是这样做是没有意义的,所以只需将它用作您希望它表现为的类

这篇文章比我解释得更好

原因是: 首先,java使用静态绑定从一组重载方法中进行选择。然后在从重写的方法集中进行选择时使用动态绑定。


我认为你理解为什么要打印前三行,所以我不会解释这背后的原因

所以就这样想吧。无论何时“扩展”到一个类,实际上都是在创建该类的新副本并向其中添加内容。 如果您将一个类想象成一个包含房间(方法)和设备(变量)的房子的蓝图,那么一个扩展另一个类的类就是一个基于另一个蓝图的房子的蓝图,其中包含一些可能的修改/添加。当您创建扩展另一个蓝图的蓝图时,您添加的任何房间或设备,如果与原始蓝图中的某个内容具有相同的签名(相同的名称/类型/参数),将覆盖原始蓝图中的该内容

解释为什么每一行都像这样打印:

第4行:您创建了一个IPOD类,它只有一个方法,并打印相同的内容“来自IPOD的音乐”

第5行:您创建了一个IPOD类,它只有一个方法并打印相同的内容,“来自IPOD的音乐”。是的,该方法只接受音乐类型,而歌曲扩展了音乐。回到例子:这意味着音乐之家的房间和设备都在歌曲之家内部。因此,由于该方法不寻找歌曲库,因此它会删除不属于音乐库的所有内容并将其丢弃。然后将音乐之家交给IPOD类内部的方法

第6行:您创建了一个IPOD类,它只有一个方法,并打印相同的内容“来自IPOD的音乐”。SM是一个音乐对象,因此它很容易传递给方法

第8行:因此第8行由以下代码行组成:

IPOD ipl = new IpodPlayer();
Song s = new Song();
ipl.PlayMusic(s);
ipl属于IPOD类,而不是IpodPlayer类。IPOD类中没有对象歌曲的方法。当您写入“IPOD ipl=new IpodPlayer();”时,您并没有创建IpodPlayer对象。您正在创建一个IPOD对象。 在本文中,当您说“new iPodLayer”时,实际上是说使用iPodLayer蓝图构建IPOD对象。IPOD对象是一个具有一个方法“void PlayMusic(Music m)”的类。所以ipl只有一种方法(音乐方法)。 它之所以说“来自Ipod播放器的音乐”,而不是“来自Ipod的音乐”,是因为在使用Ipod播放器蓝图构建Ipod对象时,您使用具有相同符号(void PlayMusic(Music m))的Ipod播放器方法覆盖了Ipod方法。这仅仅是因为IpodPlayer正在扩展IPOD类


第7行和第9行:IPL是一个IPOD类,但是在声明期间,您可以使用IpodPlayer类中相同的命名方法覆盖名为“PlayMusic”的方法。这就是为什么m、s和sm都打印出“来自IpodPlayer的音乐”

核心部分:整个概念是关于方法重载和重写,以及它们如何与动态和静态绑定相联系

现在,首先看下面的代码片段,它是对您的案例@run-time的简化,并理解运行时的图片。使用您选择的任何IDE调试您的代码,您将看到完全相同的结果

主要外卖:在运行时,您的引用将解析为实际对象,这称为动态绑定或多态性。运行时表示对象。因此,无论
IpodPlayer iplayer=new IpodPlayer()或<代码>IPOD ipl=新IpodPlayer()
,在运行时您将获得
IpodPlayer
的实例,并将调用其方法

动态绑定链接到方法覆盖。因此,在运行时,将调用哪个被重写的方法是通过检查对象类型来决定的。因此,您可以看到,无论引用类型是什么,在运行时都会调用实际对象的方法

这总结了动态绑定和方法重写

静态绑定和方法重载

静态绑定明确了java中重载方法在编译时如何使用类型信息进行绑定

现在,您的案例是
IPOD=new IPOD()
非常清楚,因为您只有方法,没有重载方法,所以您的结果4、5和6是自解释的

真正的困惑在于
IpodPlayer iplayer=new IpodPlayer()
IPOD ipl=新的IpodPlayer()

编译时根据对象类型决定调用哪个重载方法,无论是
PlayMusic(Music m)
还是
PlayMusic(Song m)
请注意,我只谈论方法,而不是哪个类或对象。 new IpodPlayer().PlayMusic(new Music()); //Music from IpodPlayer new IpodPlayer().PlayMusic(new Song()); //Song from IpodPlayer new IpodPlayer().PlayMusic(new Song()); //Music from IpodPlayer new IPOD().PlayMusic(new Music()); //Music from Ipod new IPOD().PlayMusic(new Song()); //Music from Ipod new IPOD().PlayMusic(new Song()); //Music from Ipod new IpodPlayer().PlayMusic(new Music()); //Music from IpodPlayer new IpodPlayer().PlayMusic(new Song()); //Music from IpodPlayer new IpodPlayer().PlayMusic(new Song()); //Music from IpodPlayer