创建子类的两种方法实际上是相同的?

我是 Java 新手。我创建了一个超类和一个从它扩展的子类:


class Car {

    private String name;

    private int wheels;


    public Car(String name, int wheels) {

        this.name = name;

        this.wheels = wheels;

    }

}


class Ford extends Car {

    public Ford(String name, int wheels) {

        super(name, wheels);

    }


}

然后在 main 方法中我可以创建超类和子类的实例:


  Car car = new Car("car", 4);


   Ford ford = new Ford("ford", 6);


   Car ford2 = new Ford("ford", 6);

我只是想问一下,创建实例时以 Ford 开头,还是以 Car 开头,有什么区别吗?正如您所看到的 ford 和 ford2 的创建方式不同。请注意,我知道 ford 和 ford2 不一样,因为它们是具有不同指针的引用变量。我只是想知道它们创建的语法。谢谢


编辑:


我发现了差异,但不明白其背后的逻辑。


如果您在 Car 类中有一个方法,您可以从 ford 和 ford2 调用它

如果您在 Car 和 Ford 类中有一个同名的方法,您可以从 ford 和 ford2 调用它,并且它将调用子类中的方法

如果您仅在 Ford 类中拥有一个方法,则无法从 ford2 中调用它 - 您将收到错误。

我真的不明白为什么,ford2仍然是福特的一个实例


蝴蝶刀刀
浏览 158回答 5
5回答

富国沪深

到目前为止,我真的不喜欢这些答案。他们正在把简单的事情变得复杂起来。变量只是一个引用的持有者。正如您从示例中看到的,变量的类型不必与其所保存的引用的确切类型相匹配。该变量只需等于或比其引用更通用(或者,如果您愿意,等于或不那么具体)。Car比 更通用Ford,因此该分配是可以的。每个引用都可以由变量保存Object,因为这是Java 中存在的最通用的类型。Object foo = new Car(1, 6);Object bar = "hello world";现在,使用这些变量的困难在于我们只能调用类中的方法Object。通过将变量声明为Object,当我尝试访问内容时,我只能使用方法,无论Object其中实际存储了什么。Object(例如)有几个方法toString,所以这可能没问题,但在大多数情况下分配给Object并不是很有用。因此,我们对变量越具体,我们可能访问的功能就越多。当你说Car car = new Ford("ford", 6);当从此变量引用它时,我们可能无法访问一些福特特定的功能。我们总是可以稍后通过强制转换实例来解决这个问题,但除非绝对必要,否则应该避免这样做。然而,我们越通用,我们的代码就越灵活。如果一个方法只以福特汽车作为参数,那是相当有限制的。如果可以取任何一辆车作为参数,那就更加灵活了。一般来说,在为变量选择正确的类型时,您可以在心里尽可能地从最通用的类型开始,然后不断使其变得更加具体,直到它适合您的用例。例如,如果您可以选择“prefer Iterableover a” Collection、“prefer Collectionover a” List、“prefer Listover an” ArrayList。

不负相思意

  Ford ford = new Ford("ford", 6);      Car ford2 = new Ford("ford", 6);两个对象变量都引用福特类对象。但对象变量的类型不同。就像福特是福特的类型,但福特2是汽车的类型。它被称为概括对象创建。始终建议概括对象引用创建,因为您可以通过分配继承相同超类的不同类型的子类来更改对象引用类型。除此之外,下面提到的差异也是一个有用的情况。Car car = new Car("car", 4);该汽车对象只能访问 Car 类方法。Ford ford = new Ford("ford", 6);该对象可以访问两个类的所有方法。但是假设你在两个类中都有如下所示的 1 个方法   public static void a(){         system.out.println("static method");    }如果福特对象调用方法a()。它将运行子类中存在的方法。因为 Ford 变量是 Ford 子类的类型。 Car ford2 = new Ford("ford", 6);该对象可以访问两个类的所有方法。但是假设你在两个类中都有如下所示的 1 个方法   public static void a(){         system.out.println("static method");    }如果福特对象调用方法a()。它将运行超类中存在的方法。因为 ford2 变量是 Ford 超类的类型。

幕布斯7119047

我只是想问一下福特和福特2有什么区别吗?或者它们完全一样吗?最好的答案是:这取决于。这取决于您所说的“相同”到底是什么意思。在Java中,new需要操作符来创建一个新对象。因此,这两个赋值会将新创建的对象分配给变量ford和ford2。这些对象将具有不同的引用,因此在 JVM 中具有不同的标识。结果,以下内容将评估为false:boolean b = (ford == ford2);然而,这两个对象可以说具有相同的属性,因为它们的实例字段包含相同的值。就目前而言,该表达式的计算结果也为false:boolean b = (ford.equals(ford2));equals()因为从Object分配变量的两种类型(即Car和)继承的默认方法Ford执行与上一条语句中评估的相同的引用比较。如果类equals()中的方法Ford被重写以执行值比较(而不是默认的引用比较),如下所示:@Override boolean equals(Object ob) {     if (!(ob instanceof Ford)) return false;         Ford f = (Ford) ob;             return this.name.equals(f.name) && this.wheels == f.wheels; }那么下面的表达式将计算为true:boolean b = ford.equals(ford2);TL;DR:变量引用的对象ford具有ford2相同的类型(即它们都是Fords)、相同的属性,但不同的标识。如果如图所示为类定义了值比较Ford,那么它们将具有相同的值,否则它们不会。

四季花海

从技术上讲,它们不一样 -==会给出false- 但它们保存相同的数据(不一样意味着修改一个不会影响另一个)并且它们是相同的类型。但是,您只能通过将ford2其强制转换来调用仅在Ford类中定义的方法(如果有的话)Ford(在这种状态下,ford2您只能调用Car的方法)。

拉丁的传说

您可以调用Ford上的任何方法ford。您可以调用Car上的任何方法ford2。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java