【问题标题】:Problem with constructor that will create rectangle using coordinates of the centers, high (X axis) and width (y axis)构造函数的问题,它将使用中心坐标、高(X 轴)和宽度(y 轴)创建矩形
【发布时间】:2020-08-30 10:25:59
【问题描述】:

所以我需要由 2 个类组成的代码,已经形成的方法点和方法矩形,其中包括用于创建矩形本身的构造函数,矩形本身应该由这个测试形成

@Test
    public void testRectangle2() {
        Rectangle rect = new Rectangle(20, 30, 20, 20);
        assertAll(
                () -> assertEquals(10, rect.getTopLeft().getX()),
                () -> assertEquals(20, rect.getTopLeft().getY()),
                () -> assertEquals(30, rect.getBottomRight().getX()),
                () -> assertEquals(40, rect.getBottomRight().getY()),
                () -> assertEquals(20, rect.getWidth(), 20),
                () -> assertEquals(20, rect.getHeight(), 20)
        );
    }

类点工作正常,我只是为了清楚起见而添加它

public class Point {
    private int x, y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public Point() {
        this(0, 0);
    }
    public int getX() {
        return x;
    }
    public void setX(int x) {
        this.x = x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y) {
        this.y = y;
    }
    public void moveTo(int newX, int newY) {
        x = newX;
        y = newY;
    }
    public void moveRel(int dx, int dy) {
        x += dx;
        y += dy;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        result = prime * result + y;
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Point other = (Point) obj;
        if (x != other.x)
            return false;
        if (y != other.y)
            return false;
        return true;
    }
}

这是 Rectangle 本身的类,它包括构造函数和附加方法。

public class Rectangle {
    public int width = 0;
    public int height = 0;
    public Point center;
    public int xCenter;
    public int yCenter;

    public Point getTopLeft() {
        Point point = new Point(center.getX(), center.getY());
        point.moveRel(- width / 2, - height / 2);
        return point;
    }

    public Point getBottomRight() {
        Point point = new Point(center.getX(), center.getY());
        point.moveRel(width / 2,  height / 2);
        return point;
    }

    public int getWidth() {

        return width;
    }


    public int getHeight() {

        return height;
    }
    public Point getCenter() {
       Point center = new Point(xCenter, yCenter);
       return center;
    }
    public Rectangle(int xCenter, int yCenter, int width, int height) {
        this.xCenter=xCenter;
        this.yCenter=yCenter;
        this.width=width;
        this.height=height;
    }
}

问题在于它自己的构造函数,它应该从测试中获取值,然后形成矩形,但它没有这样做。

【问题讨论】:

  • 为什么你从不调用getCenter() 或以其他方式构造代表矩形中心的Point?这很关键。
  • 所以point 是我无法修改的预建类。而且我有点不确定如何调用getCenter(),因为我什至不确定我是否正确地做到了,所以getCenter()public Rectangle(int xCenter, int yCenter, int width, int height) 是我有问题的部分
  • 没有人说你应该修改Point。你调用getCenter() 就像调用任何其他方法一样。有很多事情你没有“正确地”做,但我没有看到你做的任何事情都做得不正确,以至于它不会起作用。问题是您的矩形没有中心,因为您的代码中没有任何地方初始化相应的字段。

标签: java constructor rectangles


【解决方案1】:

这段代码有几个问题。

构造函数的问题是没有创建中心点,然后测试失败,getTopLeft/getBottomRight 中的NullPointerException 先调用,因为这些方法不使用getCenter() 方法,而是直接引用center 字段。

所以,只要在上述方法中使用上述getter并删除冗余字段center就足够了。

class Rectangle {
    public int width = 0;
    public int height = 0;
    public int xCenter;
    public int yCenter;

    public Point getTopLeft() {
        Point point = getCenter();
        point.moveRel(- width / 2, - height / 2);
        return point;
    }

    public Point getBottomRight() {
        Point point = getCenter();
        point.moveRel(width / 2,  height / 2);
        return point;
    }

    public int getWidth() {

        return width;
    }


    public int getHeight() {

        return height;
    }
    public Point getCenter() {
       Point center = new Point(xCenter, yCenter);
       return center;
    }
    public Rectangle(int xCenter, int yCenter, int width, int height) {
        this.xCenter=xCenter;
        this.yCenter=yCenter;
        this.width=width;
        this.height=height;
    }
}

但是,这种设计存在一定的缺陷,Rectangle 字段是公开的,可以从外部更改,从而破坏了封装原则。此外,虽然可能会重复使用,但也会创建冗余点。

Rectangle 类的改进版本如下:

  • “不可变”字段
  • 延迟初始化topLeftrightBottom
public class Rectangle {
    private final int width;
    private final int height;
    private final int xCenter;
    private final int yCenter;
    
    private Point topLeft;
    private Point bottomRight;
    
    public Rectangle(int xCenter, int yCenter, int width, int height) {
        this.xCenter = xCenter;
        this.yCenter = yCenter;
        this.width = width;
        this.height = height;
    }

    public Point getTopLeft() {
        if (null == topLeft) {
            topLeft = getCenter();
            topLeft.moveRel(- width / 2, - height / 2);
        }
        return topLeft;
    }

    public Point getBottomRight() {
        if (null == bottomRight) {
            bottomRight = getCenter();
            bottomRight.moveRel(width / 2,  height / 2);    
        }
        return bottomRight;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }
    
    public Point getCenter() {
       return new Point(xCenter, yCenter);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 2017-01-11
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多