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
Java——静态和动态;动态类型--”;这印的是什么;_Java_Oop_Inheritance_Dynamic_Static - Fatal编程技术网

Java——静态和动态;动态类型--”;这印的是什么;

Java——静态和动态;动态类型--”;这印的是什么;,java,oop,inheritance,dynamic,static,Java,Oop,Inheritance,Dynamic,Static,所以我在理解这个类中展示的示例时遇到了一些困难——它应该说明Java中静态和动态类型之间的微妙之处 public class Piece { public static void main (String[] args) { Piece p2 = new Knight(); Knight p1 = new Knight(); p1.capture(p2); // call 1; "Knight is bored" is supposed

所以我在理解这个类中展示的示例时遇到了一些困难——它应该说明Java中静态和动态类型之间的微妙之处

public class Piece {

    public static void main (String[] args) {
        Piece p2 = new Knight();
        Knight p1 = new Knight();
        p1.capture(p2); // call 1; "Knight is bored" is supposed to be printed
        p2.capture(p1); // call 2; "knight is bored" is supposed to be printed
    }

    public void capture () {
        System.out.println("Capturing");
    }

    public void capture (Piece p) {
        System.out.println("I'm bored")
    }

public class Knight extends Piece {

    public void capture (Piece p) {
        System.out.println("Knight is bored");
    }

    public void capture (Knight k) {
        System.out.println("TOO SLOW BUDDY");
    }
}
以下是我对这两个电话的理解:

呼叫1:p1.捕获(p2)

捕获方法从p1调用。通过动态类型查找,可以看到p1的动态类型是Knight。所以它看起来是在Knight子类中。p2作为参数传入。为了查看在Knight子类中调用哪个捕获方法,它检查p2的静态类型,这是一个片段。因此,印刷了“骑士无聊”。这是正确的输出,但我的推理正确吗

呼叫2:p2.捕获(p1)

使用相同的推理,从p2调用捕获方法。通过动态类型查找,可以看到p2的动态类型是Knight。所以它看起来是在Knight子类中。p1作为参数传入。要查看要调用哪个捕获方法,它将查看p1的静态类型,即Knight。因此,打印“太慢的伙伴”。显然,我的推理是错误的,因为这不是真正的印刷品。有什么方向吗


谢谢

我记得,我已经学会了“扩展”的意思是“将新的放在旧的上面,但不删除它”,如果您要“覆盖”该方法,它就像您描述的那样。
在您的情况下,如果调用“p1.capture(p1)”,应该会导致“太慢了,伙计”(但我没有尝试)。

我不认为此示例告诉您静态类型和动态类型之间的区别。您甚至不需要考虑超类和子类。它只是告诉您方法定义。-->只有当调用方、方法名称、参数名称和参数类型都相同时,才会调用正确的方法。

在第二次调用中,只能调用Piece类的方法或其子类中的相同方法。这就是为什么它将调用捕获(p件)而不是捕获(骑士k件)。后者是骑士阶级特有的


例如,当我们有“List a=new Arraylist();”时,您只能调用在List中声明的方法,而不能调用Arraylist中外观相似的附加方法。

当您将
@Override
注释添加到
Knight
的方法时,它变得清晰起来

public void capture (Knight k) {
    System.out.println("TOO SLOW BUDDY");
}
此方法未被重写-它是新的,添加到
Knight
类中

因此,它只能用于类型为
Knight
的对象,例如:
Knight k=newknight()

您没有这样的示例,即在
Knight
上以
Knight
作为参数调用此方法。您在带片骑士和带片骑士上调用了
capture

    p1.capture(p2); // call 1; "Knight is bored" is supposed to be printed
    p2.capture(p1); // call 2; "knight is bored" is supposed to be printed
    p1.capture(p1); // call 3:  TOO SLOW BUDDY <- look here :)
p1.捕获(p2);//呼叫1;“骑士无聊”应该是印刷出来的
p2.捕捉(p1);//呼叫2;“骑士无聊”应该是印刷出来的
p1.捕捉(p1);//呼叫3:太慢了,伙计
在这里,您正在对工件类对象调用捕获方法,因为您已经传递了p1(Knight)类引用,所以它将调用Knight类的重写捕获方法。就是

 public void capture (Piece p) {
        System.out.println("Knight is bored");
    }

如果运行以下代码-

public class Piece {

public static void main (String[] args) {
    Piece p2 = new Knight();
    Knight p1 = new Knight();
    p1.capture(p2); 
    p2.capture(p1); 
}

public void capture () {
    System.out.println("Capturing");
}

public void capture (Piece p) {
    System.out.println("I'm bored");
}
}

}

结果是——

我很无聊

我很无聊


因此,动态查找检查子类是否重写了函数

是的,p1。捕捉(p1)会导致“太慢的伙伴”;然而,我感到困惑的是另外两个案例,而不是这个案例;)嗯。因为p2的静态类型是一个片段,所以它只知道捕获(片段p)方法,而不知道捕获(骑士k)方法?那么,它是如何进入Knight子类并获取该方法的版本的呢?抱歉,还是有点困惑。那是因为骑士扩展了一块,p2是骑士对象。这意味着您只能调用Piece方法,但如果Knight有一个具有相同签名的方法,它将调用该方法。您的意思是p2是Piece类型的对象吗?@RyanYu:是的,与我的示例中的
a
在其余代码中是
列表的方式相同。但是当在
a
上调用方法时,它被认为是
ArrayList
@RyanYu:我认为p2是类型Piece的引用和类型Knight的对象。。希望它能回答你…好的,谢谢。当你说“它只能用于Knight类型的对象”时,你指的是它们的静态类型,对吗?换句话说,骑士n;将属于knight类型。@Ryan Yu,您有两种类型-引用类型和动态对象对象:
type staticTypeOfReference=new dynamicpolimorficObjects that canextendtypedeclared():)好的,让我看看我是否有这个权利,最后:对于p1.capture(p2),它看到p1的类型是Knight&p2的类型是Piece,所以它在Knight子类中检查一个捕获方法,该方法将Piece作为参数。它发现了这一点,并打印出“骑士很无聊”,此外,对于p2.capture(p1),它看到p2是类型片,p1是大小骑士。它查看正在从中调用捕获的类(p2--Piece),发现没有接受Knight类型参数的方法。但是有一个方法接受Piece类型的参数!然后,动态查找告诉该方法在子类(Knight)中签入一个方法,该方法覆盖它找到的这个捕获方法。然后,它使用这个覆盖方法打印“Knight is bored”。@Ryan Yu-
此外,对于p2.capture(p1),它看到p2是类型Piece
-这里p2的类型无关紧要,它被直接解析为Knight,静态解析发生在您将对象传递给某个方法时-然后检查静态类型,对其子类的实际引用根本不重要<代码>p2.capcure(p1)
-此调用知道p2是Knight类的对象,引用类型为Piece(但在这里并不重要…),并且它知道p1的引用类型为Knight(调用构造函数的最后一方),即Piece的子类。
public class Piece {

public static void main (String[] args) {
    Piece p2 = new Knight();
    Knight p1 = new Knight();
    p1.capture(p2); 
    p2.capture(p1); 
}

public void capture () {
    System.out.println("Capturing");
}

public void capture (Piece p) {
    System.out.println("I'm bored");
}
  class Knight extends Piece {


  //    public void capture (Piece p) {
  //        System.out.println("Knight is bored");
  //    }

public void capture (Knight k) {
    System.out.println("TOO SLOW BUDDY"+k);
}