例如,当我有一个类Rectangle和一个类Square。如果类Square扩展Rectangle,则class square是Rectangle类的子类。现在说我有代码。 Rectangle shape = new Square(5,6);
我会创建一个对象,但是它会是Rectangle类型,但是使用square的构造函数或Square的对象?我的混淆开始于类Square具有相同的Rectangle类方法,但它会使用类中的方法Square不是类Rectangle。那么我是否创建了一个Square对象,但是类型为Rectangle?
评论:每个人都生气,因为知道square不会扩展矩形,但这是我的老师示例纯粹显示继承,事实上最后他展示了如果我们使用这个代码,它会创建一个bug。
答案 0 :(得分:2)
这让很多人感到困惑。让我试着把它分解。
当您说new Square
时,使用Square
构造函数创建对象。该对象在其存在期间将具有类型Square
。
当您声明一个类型为Rectangle
的变量,即Rectangle x;
或Rectangle x = (anything);
时,您告诉编译器x
(当它不为空时)将始终为引用Rectangle
或其任何子类(包括Square
)。当您说Rectangle x = new Square(...)
时,x
将引用Square
,即Rectangle
。 但,x
稍后可能会被重新分配,成为不是Rectangle
的其他Square
。
这意味着,当你说x.method(...)
时,编译器只允许你使用Rectangle
中定义的方法,因为编译器只知道x
是Rectangle
1}}或某个子类。如果您在Square
中声明了一种新方法,则无法将其用于上述调用。
但是,如果x
仍然是对Square
的引用,那么当您调用Rectangle
中定义的方法时,程序将实际运行您为{{1}编写的方法(如果你覆盖了Square
中的那个)。
也许这个例子会有所帮助。假设Rectangle
声明Rectangle
方法public
和aaa
。在bbb
中,您编写了一个重写方法Square
,您没有覆盖aaa
,并声明了一个新的公共方法bbb
。
ccc
希望这有帮助。
答案 1 :(得分:1)
您创建了一个Square类型的对象。
对new Foo(...)
的调用总是创建一个Foo,没有例外。并且它总是会调用Foo
的构造函数,同样没有例外。也就是说,如果Foo从另一个类扩展,那么Foo的构造函数将要做的第一件事就是调用超类的构造函数。同样,对此没有任何例外 - 尽管你不一定会在代码中看到它,因为如果你没有调用super(...)
并且超类中存在无参数构造函数,然后编译器将自动为您调用该构造函数。但无论如何,它总会被调用。
由于您已将Square设置为矩形,因此该对象也是Rectangle的实例。对于您的类,Square总是一个Rectangle,但并非所有Rectangle都是Squares。
Rectangle shape
位只是意味着只要编译器知道,它就是“至少”一个Rectangle。它可能正好是一个Rectangle,或者它可能是Rectangle的子类(如Square) - 但它不会是例如Number。
当你调用shape.getArea()
(例如)时,JVM将查找实际类型的shape
- 不仅仅是它的编译时类型,而是它的类型实际上是在调用new
时创建的 - 并调用该类定义的方法。
答案 2 :(得分:0)
继承始终为您的对象提供is-a relationship。因此,凭借Square
延长Rectangle
,可以肯定地说Square
是-a Rectangle
。
您已创建Square
的实例,但您只能使用其父Rectangle
提供的方法。
答案 3 :(得分:0)
你要找的是回答问题“方块真的是一个矩形吗?”。从gemoetry的角度来看答案是肯定的,但从软件的角度来看答案可能并不那么明显。 “Is-a”关系必须遵循Liskov Substitution principle。
基本上,如果基类有一些不适用于派生类的方法,那么它不是“is-a”关系。
e.g。
类Rectangle {
/ 构造函数代码 /
public void changeWidth(){....} public void changeLength(){....}
}
changeWidth和changeLength是两个函数,它们对于矩形而言是完全有意义的,但对于Square则不是,因为所有边都是正方形的。虽然从我的观点来看,你可以破解并给出你自己在方形类中实现这两种功能的关系看起来并不自然。
至于其他答案,我同意他们的看法。
答案 4 :(得分:-2)
这就是所谓的多态性,做你的功课。 shape变量只是一个引用,但真实对象是一个Square对象。