You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

继承类类型转换问题:如何将Square转为Rectangle格式输出

问题

我定义了Shape、Rectangle、Square三个类,其中Shape是父类,Rectangle继承Shape,Square继承Rectangle。现有如下代码逻辑:

for (int i = 0; i < 2; i++){
    x = Math.random() * 100;
    y = Math.random() * 100;

    if (i % 2 == 0){
        width = Math.random() * 100;
        height = Math.random() * 100;
        Rectangle z = new Rectangle(x, y, height, width);
        list.add(z);
    }else if (i % 2 == 1){
        side = Math.random() * 100;
        Square z = new Square(x, y, side);
        list.add(z);
    }
}

for(Shape s : list){
   System.out.println(s.getStr0());
   System.out.println(s.getStr1());
}

当前运行输出:

Rectangle with height: 91.19 and width: 73.70, Centered at X: 14.21 Y: 81.81
Has area: 6720.81
Has perimeter: 329.78

Square with side: 66.42, Centered at X: 36.06 Y: 95.86
Has area: 4411.18
Has perimeter: 265.67

我希望通过类型转换或其他转换操作,让Square实例以Rectangle的格式输出,期望结果:

Rectangle with height: 91.19 and width: 73.70, Centered at X: 14.21 Y: 81.81
Has area: 6720.81
Has perimeter: 329.78

Rectangle with height: 66.42 and width 66.42, Centered at X: 36.06 Y: 95.86
Has area: 4411.18
Has perimeter: 265.67

完整代码如下:

import java.util.ArrayList;
public class Shape{
    private double x;
    private double y;
    private StringBuilder str = new StringBuilder();
    private StringBuilder str0 = new StringBuilder();
    private StringBuilder str1 = new StringBuilder();
    private StringBuilder str2 = new StringBuilder();

    public Shape(double x, double y){
        this.x = x;
        this.y = y;  
        String x1 = String.format("%.2f",this.x);
        String y1= String.format("%.2f",this.y);
        getStr().append("Centered at X: " + x1 + " Y: " + y1 );
    }

    public Shape(){
    }

    public static void main(String[] args){
        System.out.println('\u000C');

        ArrayList<Shape> list = new ArrayList<Shape>();
        double x;
        double y;        
        double height;
        double width;
        double side;

        for (int i = 0; i < 2; i++){
            x = Math.random() * 100;
            y = Math.random() * 100;

            if (i % 2 == 0){
                width = Math.random() * 100;
                height = Math.random() * 100;
                Rectangle z = new Rectangle(x, y, height, width);
                list.add(z);
            }else if (i % 2 == 1){
                side = Math.random() * 100;
                Square z = new Square(x, y, side);
                list.add(z);
            }
        }

        for(Shape s : list){
            System.out.println(s.getStr0());
            System.out.println(s.getStr1());
        }
    }
    public String toString(){
        String x = String.format("%.2f",this.x);
        String y = String.format("%.2f",this.y);
                
        return "Centered at X: " + x + " Y: " + y ;
    }
    public double calculateArea(){
        return -999.99;
    }
    public double calculateCircumference(){
        return -999.99;
    }
    public double calculatePerimeter(){
        return -999.99;
    }
    public double getX(){
        return this.x;
    } 
    public void setX(double x){
        this.x = x;
    }
    public double getY(){
        return this.y;
    }
    public void setY(double y){
        this.y = y;
    }
    public StringBuilder getStr(){
        return this.str;
    } 
    public void setStr(StringBuilder str){
        this.str = str;
    }
    public StringBuilder getStr0(){
        return this.str0;
    }
    public void setStr0(StringBuilder str0){
        this.str0 = str0;
    } 
    public StringBuilder getStr1(){
        return this.str1;
    } 
    public void setStr1(StringBuilder str1){
        this.str1 = str1;
    }    
}

public class Rectangle extends Shape{
    private double height;
    private double width;
    
    public Rectangle(double x, double y, double height, double width){
        super(x, y);
        this.height = height;
        this.width = width;
        
        String area = String.format("%.2f",this.calculateArea());
        String perimeter = String.format("%.2f",this.calculatePerimeter());
        
        getStr0().append(toString());        
        getStr1().append("Has area: " + area + "\n");
        getStr1().append("Has perimeter: " + perimeter + "\n");
        
    }
    public Rectangle(){
        
    }
    public double calculateArea(){
        return height * width;
    }
    public double calculatePerimeter(){
        return 2 * height + 2 * width;
    }
    public String toString(){
        
        String height = String.format("%.2f",this.height);
        String width = String.format("%.2f",this.width);        
        return "Rectangle with height: " + height + " and width: " + width +
        ", " + super.toString();
    }
}

public class Square extends Rectangle{
    double side;
    StringBuilder squarestr = new StringBuilder();

    public Square(double x, double y, double side){
        super(x, y, side, side);
        this.side = side;

        String area = String.format("%.2f",this.calculateArea());
        String perimeter = String.format("%.2f",this.calculatePerimeter());

        getStr0().delete(0,getStr0().length() );
        
        getStr1().delete(0,getStr1().length() );

        getStr0().append(toString());
        
        getStr1().append("Has area: " + area + "\n");
        getStr1().append("Has perimeter: " + perimeter + "\n");
        
    }

    public String toString(){

        String side = String.format("%.2f",this.side);

        return "Square with side: " + side + ", " + getStr() ;
    }

    public double calculateArea(){
        return side * side;
    }

    public double calculatePerimeter(){
        return 4 * side;
    }
}
解决方案

可以实现,以下是几种可行思路:

方法1:遍历判断类型并强制转换输出

直接修改遍历逻辑,判断实例类型,若为Square则强制转换为Rectangle(Square继承自Rectangle,转换安全),调用Rectangle的输出逻辑:

for(Shape s : list){
    if (s instanceof Square) {
        Rectangle rect = (Rectangle) s;
        String area = String.format("%.2f", rect.calculateArea());
        String perimeter = String.format("%.2f", rect.calculatePerimeter());
        System.out.println(rect.toString());
        System.out.println("Has area: " + area);
        System.out.println("Has perimeter: " + perimeter + "\n");
    } else {
        System.out.println(s.getStr0());
        System.out.println(s.getStr1());
    }
}

此方法无需修改类结构,仅调整输出逻辑,适合临时需求。

方法2:修改Square类的toString方法

Square本质是长宽相等的Rectangle,直接让其toString复用Rectangle的格式:

public String toString(){
    String sideStr = String.format("%.2f",this.side);
    return "Rectangle with height: " + sideStr + " and width: " + sideStr +
           ", " + super.toString();
}

同时删除Square构造函数中对str0、str1的重置代码(父类Rectangle已完成初始化):

public Square(double x, double y, double side){
    super(x, y, side, side);
    this.side = side;
}

此方法从类定义层面统一输出格式,符合面向对象设计逻辑。

方法3:重构字符串生成逻辑(推荐)

当前构造函数提前生成str0、str1的逻辑不够灵活,建议将字符串生成逻辑改为动态调用:

  1. 在Rectangle类中添加统一输出方法:
public String getDisplayInfo() {
    return toString() + "\n" +
           "Has area: " + String.format("%.2f", calculateArea()) + "\n" +
           "Has perimeter: " + String.format("%.2f", calculatePerimeter());
}
  1. Square类直接复用父类的输出方法:
public String getDisplayInfo() {
    return super.getDisplayInfo();
}
  1. 遍历输出时调用该方法:
for(Shape s : list){
    if (s instanceof Rectangle) {
        System.out.println(((Rectangle)s).getDisplayInfo() + "\n");
    }
}

此方法解耦了对象创建与输出格式,后续调整格式更便捷。

内容的提问来源于stack exchange,提问作者DCR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 02:17:14