继承类类型转换问题:如何将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的逻辑不够灵活,建议将字符串生成逻辑改为动态调用:
- 在Rectangle类中添加统一输出方法:
public String getDisplayInfo() { return toString() + "\n" + "Has area: " + String.format("%.2f", calculateArea()) + "\n" + "Has perimeter: " + String.format("%.2f", calculatePerimeter()); }
- Square类直接复用父类的输出方法:
public String getDisplayInfo() { return super.getDisplayInfo(); }
- 遍历输出时调用该方法:
for(Shape s : list){ if (s instanceof Rectangle) { System.out.println(((Rectangle)s).getDisplayInfo() + "\n"); } }
此方法解耦了对象创建与输出格式,后续调整格式更便捷。
内容的提问来源于stack exchange,提问作者DCR
相关产品推荐
相关产品推荐

