Java 方形和矩形继承
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23353468/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Square and Rectangle Inheritance
提问by theGreenCabbage
This is a question in-regards to basic inheritance in Java with two classes.
这是一个关于 Java 中具有两个类的基本继承的问题。
We have two classes, with the first one being a Rectangle
:
我们有两个类,第一个是 a Rectangle
:
private double length;
private double width;
public Rectangle(double length, double width)
{
this.length = length;
this.width = width;
}
Next we have an extension class called Square
, which extends Rectangle
, so through super()
we know that it uses the constructor of the Rectangle
class.
接下来我们有一个名为 的扩展类Square
,它 extends Rectangle
,因此super()
我们知道它使用了Rectangle
类的构造函数。
private double side;
public Square(double side)
{
super(side, side);
this.side = side;
}
public void print()
{
System.out.println("I am a square of side " + side);
}
This is our main:
这是我们的主要内容:
Square b = new Square(6.0);
Rectangle c = (Rectangle) b;
c.print();
We create a object of the type Square
, which would contain two side
variables the double
6.0
我们创建一个类型为 的对象Square
,它包含两个side
变量double
6.0
Next, we cast b
to Rectangle
c
, which is where my question comes in.
接下来,我们投射b
到Rectangle
c
,这就是我的问题所在。
Why would c.print()
print out I am a square of side 6.0
?
为什么会c.print()
打印出来I am a square of side 6.0
?
采纳答案by Sotirios Delimanolis
This assumes Rectangle
declares a print()
method.
这假设Rectangle
声明了一个print()
方法。
This action
这个动作
Rectangle c = (Rectangle) b;
doesn't do anything to the instance referenced by b
. It only widens the reference variable b
to its super type Rectangle
.
对引用的实例没有任何作用b
。它只会将引用变量扩大b
到它的超类型Rectangle
。
Invoking print()
will have polymorphic behavior and, at runtime, the implementation of Square
will be used since c
is referencing a Square
object, which has set size
to 6
.
调用print()
将具有多态行为,并且在运行时,Square
将使用的实现,因为c
它引用了一个Square
设置size
为的对象6
。
Square b = new Square(6.0);
...
private double side;
public Square(double side) {
super(side, side);
this.side = side;
}
Note that this is the expected behavior in Java since all methods are virtual by default. In other languages like C++ and C#, your cast would have worked since print
method in Rectangle
isn't declared as virtual
.
请注意,这是 Java 中的预期行为,因为默认情况下所有方法都是虚拟的。在 C++ 和 C# 等其他语言中,由于print
方法 inRectangle
未声明为virtual
.
More info:
更多信息:
回答by Jeff Storey
This is polymorphic behavior. The actual type of the class determines the method that is called. Square
's version of print
will be called since the actual type of the object is Square
.
这是多态行为。类的实际类型决定了调用的方法。Square
的版本print
将被调用,因为对象的实际类型是Square
.
回答by Mihai Stancu
Polymorphy
多态
In (Java) inheritance that is the intended behavior -- polymorphy -- it's a way for you (the developer) to design an application around a concept (rectangles) and allow other related concepts (squares) to be used in places where the original concept (rectangle) is used but with their own (square) behavior.
在(Java)继承中,这是预期的行为——多态——它是您(开发人员)围绕概念(矩形)设计应用程序的一种方式,并允许其他相关概念(正方形)在原始的地方使用使用概念(矩形)但具有自己的(方形)行为。
Practicality
实用性
Imagine you'd have a list or array of rectangles and you'd fill it with objects received from returns of functions from outside your own package. Then you'd iterate over the list and ask each object to do things -- it is normal to want those objects to behave as what they really are, not as what they're filling in for.
想象一下,您有一个矩形列表或数组,并用从您自己的包外部的函数返回接收到的对象填充它。然后,您将遍历列表并要求每个对象执行操作——希望这些对象表现得像它们真实的样子,而不是它们所填充的那样是正常的。
If you ask a rectangle what its area is it will multiply length and width and return the result. If you don't override that in the square class it will do the same thing but you could override it and it could calculate its area as Math.pow(this.side, 2)
.
如果你问一个矩形它的面积是多少,它会乘以长和宽并返回结果。如果你不在 square 类中覆盖它,它会做同样的事情,但你可以覆盖它,它可以将它的面积计算为Math.pow(this.side, 2)
.
How about this inheritance chain:
这个继承链怎么样:
Shape > Polygon > Quadrilateral > Parallelogram > Rectangle > Square
You would definately need to implement different area calculation methods -- wouldn't you want each object to behave as its own underlying structure tells it to (instead of behaving like the type it's been cast to)?
您肯定需要实现不同的面积计算方法——您是否不希望每个对象都按照自己的底层结构告诉它的方式运行(而不是像它被强制转换的类型那样运行)?
回答by matthugs
Remember that c
is just a reference to an object in memory. The object being referenced is of dynamictype Square, despite the reference c
being of statictype Rectangle. The distinction between static and dynamic typing is crucial to this example.
请记住,这c
只是对内存中对象的引用。被引用的对象是动态类型 Square,尽管引用c
是静态类型 Rectangle。静态类型和动态类型之间的区别对于此示例至关重要。
The static type associated with a reference to an object is what the compiler uses to ensure that our code makes sense from a type perspective. When one calls a method on an object, however, which method is called depends on the dynamic type of the object, i.e. the type of object actually being referenced at runtime. This is called dynamic binding.
与对象引用相关联的静态类型是编译器用来确保我们的代码从类型角度来看有意义的类型。然而,当对对象调用方法时,调用哪个方法取决于对象的动态类型,即在运行时实际引用的对象类型。这称为动态绑定。
It also bears mentioning that the Rectangle-Square example is a canonical one. It is usually used to illustrate how thinking of types and supertypes as categories and generalizations can be misleading. Following the Liskov substitution principle requires writing the classes the other way, with Rectangle extends Square
. This is another important idea of Object-Oriented Programming being touched on.
还值得一提的是 Rectangle-Square 示例是一个规范示例。它通常用于说明将类型和超类型视为类别和概括可能会产生误导。遵循 Liskov 替换原则需要以另一种方式编写类,使用Rectangle extends Square
. 这是涉及到的面向对象编程的另一个重要思想。
回答by Ben N
Because of inheritance, every Square
is also a Rectangle
. When you cast it to shove a Square
in a Rectangle
variable, it retains its Square
ness. In this example, either a Square
or a Rectangle
can be put in your c
. Polymorphism means that the method on whatever class it reallyis will be used.
因为继承, everySquare
也是一个Rectangle
. 当您将其强制转换为将Square
a推入Rectangle
变量时,它会保留其特性Square
。在此示例中,可以将 aSquare
或 aRectangle
放入您的c
. 多态性意味着将使用它真正属于的任何类的方法。
回答by padawan
I think this is the modification you need:
我认为这是您需要的修改:
public static class Rectangle
{
protected double length;
protected double width;
public Rectangle(double length, double width)
{
this.length = length;
this.width = width;
}
public Rectangle(Rectangle r)
{
this.length = r.length;
this.width = r.width;
}
public void print()
{
System.out.println("I am a rectangle of length " + length + " and width " + width);
}
}
public static class Square extends Rectangle
{
public Square(double side)
{
super(side, side);
}
public void print()
{
System.out.println("I am a square of side " + length);
}
}
public static void main(String[] args)
{
Square b = new Square(6.0);
Rectangle c = new Rectangle(b);
c.print();
}
Your Square
class has nothing to do with Rectangle
class. It has a different attribute. If you are using inheritence, base class should inherit something.
你的Square
班级与Rectangle
班级无关。它有一个不同的属性。如果您使用继承,基类应该继承一些东西。
Moreover, there is no print()
method in Rectangle
.
此外,中没有print()
方法Rectangle
。
A simple copy constructor, making your base class members protected
and deleting the unnecessary derived class members should work.
一个简单的复制构造函数,使您的基类成员protected
并删除不必要的派生类成员应该可以工作。