繁体   English   中英

Java。 类的类型与对象

[英]Java. Type vs Object of a class

例如,当我有一个Rectangle类和一个Square类时。 如果Square类扩展Rectangle,则Square类是Rectangle类的子类。 现在说我有代码。 Rectangle shape = new Square(5,6); 我将创建一个对象,但是它将是Rectangle类型,但是使用square的构造函数还是Square的对象?,我的困惑始于类Square,它具有与Rectangle类相同的方法,但是它将使用类中的方法方形不类矩形。 那么我是否创建了Square对象,但是具有Rectangle类型?

评论:每个人都知道正方形不会扩展矩形,这让每个人都感到愤怒,但这是我的老师的例子,纯粹显示了继承性,实际上他在演示如何使用此代码如何创建错误。

这使很多人感到困惑。 让我尝试将其分解。

当您说new Square ,将使用Square构造函数创建对象。 该对象在其整个存在期间将具有Square类型。

当声明类型为Rectangle的变量时,即Rectangle x; Rectangle x = (anything); 您告诉编译器x (当它不为null时)将始终是对Rectangle 或其任何子类 (包括Square )的引用。 当您说Rectangle x = new Square(...)x将是对Square的引用,即Rectangle 但是 ,以后可以将x重新分配为其他不是Square Rectangle

这意味着,当您说x.method(...) ,编译器仅允许您使用Rectangle中定义的方法,因为编译器仅知道xRectangle或某些子类。 如果在Square声明一个新方法,则不能在上面的调用中使用它。

但是,如果x仍然是对Square的引用,那么当您调用Rectangle定义的方法时,该程序实际上将运行您为Square编写的方法(如果已覆盖Rectangle )。

也许这个例子会有所帮助。 假设Rectangle声明了public方法aaabbb Square ,您编写了重写方法aaa ,没有重写bbb ,而是声明了一个新的公共方法ccc

Rectangle x = new Square(10);
Rectangle y = new Rectangle(5,6);

// assume that x and y aren't changed 

x.aaa();   // runs the overriding method aaa in Square
y.aaa();   // runs the method aaa in Rectangle

x.bbb();   // runs the method in Rectangle, since it's not overridden.  But
           // if bbb calls aaa, then it will call the aaa in Square.
y.bbb();   // runs the method in Rectangle

x.ccc();   // illegal.  Even though the object is actually a Square, the
           // compiler isn't allowed to know that.
y.ccc();   // illegal

((Square)x).ccc();  // This is how you can get to the new method that you
           // declared in Square.  Even though the compiler doesn't know 
           // that x is a Square, when you use the cast, you tell the 
           // compiler that it's OK fo treat it as a Square, and to access
           // the method defined only in Square.
((Square)y).ccc();  // Will throw ClassCastException at runtime, because 
           // y isn't a Square.

希望这可以帮助。

您创建了一个Square类型的对象。

new Foo(...)调用将始终创建Foo,没有例外。 而且它将始终再次调用Foo的构造函数,而不会出现异常。 也就是说,如果Foo从另一个类扩展,那么Foo的构造函数要做的第一件事就是调用超类的构造函数。 再说一次,这也没有例外-尽管您不一定会在代码中看到它,因为如果您没有对super(...)的调用,并且在super中存在无参数的构造函数类,则编译器将自动为您调用该构造函数。 但是,无论哪种方式,它总是会被调用。

由于已将Square设置为一个矩形,因此该对象也是Rectangle的实例。 在您的课程中,正方形始终是矩形,但并非所有矩形都是正方形。

Rectangle shape仅表示,据编译器所知,它“至少”是Rectangle。 它可能完全是一个Rectangle,也可能是Rectangle的子类(例如Square),但不会是Number。

例如,当您调用shape.getArea() ,JVM将查找shape实际类型(不仅是其编译时类型,而且还包括您在调用new时实际创建的类型),并调用该方法。该类定义。

继承总是给您的对象一个is-a关系 因此,凭借Square扩展的Rectangle ,可以肯定地说Square Rectangle

您已经创建了Square的实例,但是您将只能在其实例上使用其父Rectangle提供的方法。

您在寻找的答案是“ Square真的是矩形吗?”。 从宝石学的角度来看,答案是肯定的,但从软件的角度来看,答案可能并不那么明显。 “是”关系必须遵循Liskov替代原则

因此,基本上,如果基类具有某些不适用于派生类的方法,则它不是“ is-a”关系。

例如

矩形类{

/ 构造函数代码 /

public void changeWidth(){....} public void changeLength(){....}

}

changeWidth和changeLength是两个函数,它们对于矩形(而不是正方形)非常有意义,因为所有边都相等。 尽管从我的角度来看,尽管您可以在平方类中破解并给出自己的两个函数的实现,但是关系看起来并不自然。

至于其他答案,我也同意。

那就是所谓的多态性,做功课。 shape变量仅是参考,而实际对象是Square对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM