Java Polymorphism/Casting/Methods

Java Polymorphism/Casting/Methods

关于这个话题的澄清。因此,出于示例目的,假设我有:

public interface Gaming {
   void play;
}

public abstract class Console implements Gaming {
   void play() {}
}

public class Xbox extends Console {
   void play() {}
}

public class XboxOne extends Xbox {
   void play() {}
}
  1. 我永远无法直接实例化 Console 因为它是 abstract
  2. 但是我可以将控制台实例化为 xbox

    主机收藏 = new Xbox();

  3. 如果所有 class 都有定义的 play() 方法。如果我调用 fav.play(); 它将查看 Xbox 的播放方法,如果它没有播放方法它会继续在层次结构中向上直到找到该方法?

  4. 此外,如果我((XboxOne)fav).play()它会执行XboxOne的播放方法吗?还有,如果它在层次结构中较低,我只能投object是真的吗?

  5. 如果 Xbox class 有一个 getGamerscore 方法但控制台没有,我会 能够运行fav.getGamerScore()?

一般问题:

= 左边的类型显示调用方法时 class(最具体)java 将查找什么? (如果在那里找不到它,它会继续沿着层次结构向上移动,直到找到该方法?)

右边的类型就是编译类型。编译时 java 会查看方法或数据是否属于编译类型,如果是则一切正常? Java 在 运行ning 时将不再查看它的编译类型。

转换只是帮助解决编译问题?就像我想使用某种方法,但我的 objects 编译类型就像一个接口或抽象 class 之类的,所以我进行强制转换,这样当我尝试访问 运行时间类型的方法?

如果我说错了请纠正我我只是想把所有的规则都记在脑子里。另外,如果有人有任何有用的资源,那就太好了。

**我发现我没有使用游戏界面

  1. 是的,如果你在XBox上调用play方法,它没有,它会调用base中的方法class。

  2. 您将无法将 Xbox 转换为派生的 class XboxOne。您只能向上转换为控制台或向下转换为您创建的实际对象 (XBox) 的类型。如果您没有首先创建 XBox,您将获得运行时 ClassCastException。

  3. 如果 XBox 获得 Gamerscore,但控制台没有。如果您按照自己的方式构造 in ,则将无法调用该方法。如果 getGamerscore 是 Console 的抽象方法,您可以调用它。

针对您的一些一般性问题。我鼓励你在互联网上四处闲逛。但简单来说,当你做这样的事情时:

Console fav =  new Xbox();

您正在构造一个 Xbox 类型的对象并分配给一个类型为 Console 的变量。出于编译时检查的目的,XBox 现在是一个控制台,可以传递给需要控制台的方法。在此处查看 post:

explicit casting from super class to subclass

  1. 是的,如果你在Xbox中覆盖了play(),那么它会被调用,否则它会使用抽象中的默认实现class。

  2. 您无法将控制台投射到 XboxOne。但是,如果您已将 fav 声明为 Xbox 类型,则可以将其转换为 XboxOne

你需要区分两件事

  1. 静态类型

这是编译时已知的以及将用于方法签名查找的内容。所以如果你有Console fav = new Xbox(),那么fav的静态类型就是Console。 因此,如果您尝试调用 fav.play(),编译器将在 Console class 中查找 play 签名;如果 Console 不支持此方法,那么 Java 甚至不会编译它。

  1. 动态类型

这是运行时的变量,所以在你启动程序后Console fav = new Xbox()fav的动态类型将是Xbox(但静态类型仍然是Console).

现在回答你的问题

If all of the classes have a defined play method. If I call fav.play(); it will look at the Xbox's play method, if it did not have a play method it would continue up the hierarchy until it found that method?

如果所有 classes 你的意思也是基础 Console class(至少是抽象方法),那么是的。

Also if I did ((XboxOne)fav).play() it would do the XboxOne's play method?, also is it true that I can only cast an object if it's lower in the hierarchy?

你总是可以向上转换——从更具体的 (Xbox) 到更通用的 (Console);向下转型只在某种程度上是可能的——如果它有机会成功的话。所以通常向下转换为动态类型应该会成功。 (例如 Console fav = new Xbox() + (Xbox)console).

If the Xbox class had a getGamerscore method but the console didn't, would I be able to run fav.getGamerScore()?

没有,如前所述; favConsole,因此不知道 getGamerScore 是什么意思。但是,您仍然可以 ((XBox) fav).getGamerScore.

Casting just helps get past compile problems?

转换可能非常危险,因为您要对变量做出假设。 如果您正在调用 ((XBox) fav).getGamerScore,那么您已经知道类型必须是 Xbox 并且 Console fav 可能是错误的,因为您不能在其中分配任何类型的控制台。

I can never instantiate Console directly because it's abstract

正确

I can however instantiate console as an xbox

Console fav = new Xbox();

正确

If all of the classes have a defined play() method. If I call fav.play(); it will look at the Xbox's play method, if it did not have a play method it would continue up the hierarchy until it found that method?

正确。这并不是现实中真正发生的事情(经过优化),但从概念上讲,你是对的。

Also if I did ((XboxOne)fav).play() it would do the XboxOne's play method?

不正确。 fav 引用的对象的具体运行时类型是 XBox。 XBox 不是 XBoxOne。所以这样的转换会因 ClassCastException 而失败。您可以将 fav 转换为 XBox,因为 fav 确实是一个 XBox

also is it true that I can only cast an object if it's lower in the hierarchy?

不确定你的意思。强制转换意味着:"I know that you, the compiler, only know that fav is a Console. But I know better than you, and I'm sure it's in fact an instance of XBox, so please consider that this variable references an XBox, so that I can call methods present in XBox but not in Console. If the runtime proves me wrong, I acept to get a ClassCastException".

If the Xbox class had a getGamerscore method but the console didn't, would I be able to run fav.getGamerScore()?

不,你不会,因为fav的编译时间是Console,而Console没有这个方法。您必须将变量转换为 XBox:

XBox xbox = (XBox) fav;
xbox.getGamerScore();

General Questions:

The type on the left of the = shows what class (most specific) java will look in when a method is called? (If it cannot find it there it will continue up the hierarchy until it finds the method?)

如果将 "left" 替换为 "right",那将是正确的。

The type on the right just stands for the compile type. When compiling java will look and see if the method or data belongs to the compile type and if so everything is good? Java will not look at it's compile type anymore when it's running.

正确的是 "right" 被 "left" 替换了。

Casting just helps get past compile problems? Like if I want to use a certain method but my objects compile type is like an interface or abstract class or something, so I cast so the compiler doesn't complain when I try to access the runtime type's methods?

正确。但是如果该对象实际上不是您转换为的类型的实例,您将在运行时得到一个 ClassCastException。

I can never instantiate Console directly because it's abstract

你是对的,但是...假设 Console 定义为

public abstract class Console implements Gaming {
   // no impl. not needed because already declared in Gaming
   // just for clarity
   public abstract void play(); 
}

您可以直接实例化 Console

Console myAnonymousConsole = new Console() {
   public void play() { System.out.println("Hello there"); }
};

I can however instantiate console as an xbox

又对了,因为 Xbox 不是 abstract

Console fav = new Xbox();

If all of the classes have a defined play() method. If I call fav.play(); it will look at the Xbox's play method, if it did not have a play method it would continue up the hierarchy until it found that method?

是的,从某种意义上说。

Also if I did ((XboxOne)fav).play() it would do the XboxOne's play method?, also is it true that I can only cast an object if it's lower in the hierarchy?

您不能相对于实际实例类型向下转型。可以写(但是味道不好)

    Console a = new XBoxOne();
    XBox b = (XBox)a; // ok because a is-a Xbox
    XBoxOne c = (XBoxOne)a; // ok because a is-a XBoxOne

    Console a = new XBox();
    XBox b = (XBox)a; // ok because a is-a Xbox
    XBoxOne c = (XBoxOne)a; // ko! because a is-not-a XBoxOne

检查在 运行 时完成。 ClassCastException 在第二个例子中抛出。

If the Xbox class had a getGamerscore method but the console didn't, would I be able to run fav.getGamerScore()?

否,如果 fav 被声明为控制台。不过,您可以在 Console 中声明 getGameScore()

General Questions:

The type on the left of the = shows what class (most specific) java will look in when a method is called? (If it cannot find it there it will continue up the hierarchy until it finds the method?)

不是真的。你必须从上到下思考继承:当一个classextends另一个时,它继承所有public(和 protected)methods/fields。例如,如果 XBoxOne 没有定义 play() 方法,它将从 XBox 继承它。 回到你的问题,就左侧类型(Console 此处)中声明的方法而言,调用的右侧方法实现将由实例的实际 运行 类型决定 - 这是多态性.

    public class XBox extends Console {
       public void play() { System.out.println("In XBox"); 
    }
    public class PS3 extends Console {
       public void play() { System.out.println("In PS3"); 
    }
    List<Console> consoles = Arrays.asList(new XBoxOne(), new PS3());
    for (Console c : consoles) {
       c.play(); // polymorphism here
    } 

打印

In XBox
In PS3

即使List 看到也只有Console类型。另请注意,XBoxOne 的实例化类型 继承了 来自 XBoxplay() 方法。

The type on the right just stands for the compile type. When compiling java will look and see if the method or data belongs to the compile type and if so everything is good? Java will not look at it's compile type anymore when it's running.

不,见上文。

Casting just helps get past compile problems?

是的,而且大部分时间都可以避免。

Like if I want to use a certain method but my objects compile type is like an interface or abstract class or something, so I cast so the compiler doesn't complain when I try to access the runtime type's methods?

我想你在这里左右混了,看上面的评论