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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 22:09:15  来源:igfitidea点击:

Square and Rectangle Inheritance

javainheritance

提问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 Rectangleclass.

接下来我们有一个名为 的扩展类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 sidevariables the double6.0

我们创建一个类型为 的对象Square,它包含两个side变量double6.0

Next, we cast bto Rectanglec, which is where my question comes in.

接下来,我们投射bRectanglec,这就是我的问题所在。

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 Rectangledeclares 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 bto its super type Rectangle.

对引用的实例没有任何作用b。它只会将引用变量扩大b到它的超类型Rectangle

Invoking print()will have polymorphic behavior and, at runtime, the implementation of Squarewill be used since cis referencing a Squareobject, which has set sizeto 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 printmethod in Rectangleisn'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 printwill 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 cis just a reference to an object in memory. The object being referenced is of dynamictype Square, despite the reference cbeing 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 Squareis also a Rectangle. When you cast it to shove a Squarein a Rectanglevariable, it retains its Squareness. In this example, either a Squareor a Rectanglecan be put in your c. Polymorphism means that the method on whatever class it reallyis will be used.

因为继承, everySquare也是一个Rectangle. 当您将其强制转换为将Squarea推入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 Squareclass has nothing to do with Rectangleclass. 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 protectedand deleting the unnecessary derived class members should work.

一个简单的复制构造函数,使您的基类成员protected并删除不必要的派生类成员应该可以工作。