【问题标题】:Refactor function overloaded methods in just one method仅在一种方法中重构函数重载方法
【发布时间】:2020-02-22 11:37:34
【问题描述】:

目前我有一个方法重载了以下方法:

    public boolean isHorizontalOrVertical(Point firstPoint, Point secondPoint) {
        return firstPoint.getFirstComponent() == secondPoint.getFirstComponent()
                || firstPoint.getSecondComponent() == secondPoint.getSecondComponent();
    }

    public boolean isHorizontalOrVertical(List<Point> points) {
        if (points == null || points.size() < 2) {
            throw new IllegalArgumentException("invalid number of points");
        }
        Point start = points.get(0);
        return points.stream()
                .allMatch(p -> isHorizontalOrVertical(start, p));
    }

需要该方法来检查两个或三个点是否相互垂直/水平。在三个点的情况下,它只需要检查最后两个点是否与起点水平/垂直。

有没有人知道我怎样才能把这一切都集中在一种方法中?

【问题讨论】:

  • 你可以使用可变参数,你可以有一个接受列表的函数?
  • 是的,但是具有所需功能的一种方法看起来如何?
  • 您为什么要这样做?我将重命名您的第二种方法,以便您可以阅读它检查列表中的 all 点是水平的还是垂直的。类似:allPointsAreHorizontalOrVertical
  • 要求调用者将两点作为列表传递有什么好处?如果您不想在公共 API 中公开两点版本,只需将该方法设为私有即可。

标签: java overloading


【解决方案1】:

首先,我必须指出,至少对我而言,这是一种计算两个实体是水平还是垂直并且这些实体是的方法是没有意义的点。两点怎么可能是水平的还是垂直的?


isHorizo​​ntalOrVertical 是个坏名字

克服上述问题,您可以创建一个计算两点是水平还是垂直的方法。

更改名称 isHorizo​​ntalOrVertical 因为它是多余的。更好的名称是 isHorizo​​ntalisVertical。该方法将返回一个布尔值,因此如果 isHorizo​​ntal 返回 false,则它是垂直的,反之亦然。 areTwoPointsHorizo​​ntal 可能是一个更好的名称,但我什至无法编写它,因为它传递了错误的信息,但请随意选择自己的名称。

那么方法,

    public boolean isHorizontal(Point first, Point second){
        boolean sameFirstComponents = firstPoint.getFirstComponent() == 
                secondPoint.getFirstComponent();
        boolean sameSecondComponents = firstPoint.getSecondComponent() == 
                secondPoint.getSecondComponent();          
        return sameFirstComponents || sameSecondComponents;
    }

最后,创建一个方法来计算列表中任意数量的点在它们之间是水平的还是垂直的(假设如果点 A 与点 B 水平,那么如果点 C 与 B 水平,那么和A一起)。

重载该方法,因为它做同样的事情,唯一改变的是参数。 (注意上面使用了简单的 isHorizo​​ntal 方法)

   public boolean isHorizontal(List<Point> points){
        boolean allPointsHorizontal = true;
        for (int i=0; i<points.size(); i++) {
            
            boolean nextPointExists = i<points.size() - 1;
            if (nextPointExists) {
                Point current = points.get(i);
                Point next = points.get(i+1);
                allPointsHorizontal = allPointsHorizontal && isHorizontal(current,next);

                if (!allPointsHorizontal)
                    return false;  
            }
        }
        
        return allPointsHorizontal;
    }

【讨论】:

    【解决方案2】:

    您可以只有一种方法,如下所示:

    public boolean isHorizontalOrVertical(List<Point> points) {
        if (points == null || points.size() < 2) {
            throw new IllegalArgumentException("invalid number of points");
        }
        if (points.size() == 2) {
           return points.get(0).getFirstComponent() == points.get(1).getFirstComponent()
                    || points.get(0).getSecondComponent() == points.get(1).getSecondComponent();
        } 
        Point start = points.get(0);
        return points.stream()
                    .allMatch(p -> isHorizontalOrVertical(List.of(start, p)));
    }
    

    注意:如果您使用的不是 Java 版本 >= 9,请使用 Arrays.asList 而不是 List.of

    【讨论】:

    • 当只有一种方法但需要两个参数时,return points.stream() .allMatch(p -&gt; isHorizontalOrVertical(start, p)); 应该如何工作?
    • List.of(..) 是什么意思?
    • 您确定 OP 使用的是 Java 版本 >= 9?
    • @EugenCovaci - 这是假设。如果不是这样,OP 将发表评论。
    【解决方案3】:

    该方法可以这样实现:

    public boolean isHorizontalOrVertical(Point firstPoint, Point secondPoint, Point thirdPoint) {
        return isHorizontalOrVertical(Arrays.asList(firstPoint, secondPoint, thirdPoint));
    }
    

    当列表为空时,您的isHorizontalOrVertical(List&lt;Point&gt;) 方法将失败,并且当列表只有一个元素时调用没有多大意义。

    我认为更好的方法是使用两个必需参数,加上一个可变参数,这样调用者必须至少给 2 分。

    private boolean are2PointsHorizontalOrVertical(Point firstPoint, Point secondPoint) {
        return firstPoint.getFirstComponent() == secondPoint.getFirstComponent()
                || firstPoint.getSecondComponent() == secondPoint.getSecondComponent();
    }
    
    public boolean arePointsHorizontalOrVertical(Point point1, Point point2, Point... rest) {
        return are2PointsHorizontalOrVertical(point1, point2) &&
            Arrays.stream(rest).allMatch(x -> are2PointsHorizontalOrVertical(point1, x));
    }
    

    就公共接口而言,这在技术上仍然是“一种方法”。如果您真的需要,您可以将帮助器are2PointsHorizontalOrVertical 替换回公共方法,但我认为这样做没有任何好处。

    【讨论】:

      【解决方案4】:

      其实你只能有一种方法:

      public boolean isHorizontalOrVertical(Point firstPoint, Point secondPoint, Point... others) {
          // check firstPoint, secondPoint for null is ommited
          if (others == null || others.length == 0) {
              return firstPoint.getFirstComponent() == secondPoint.getFirstComponent()
                      || firstPoint.getSecondComponent() == secondPoint.getSecondComponent();
          } else {
              // First, create a stream with second point + others elements
              // then match against the first point
              return Stream.of(new Point[]{secondPoint}, others).flatMap(e -> Stream.of(e))
                      .allMatch(p -> isHorizontalOrVertical(firstPoint, p));
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-04
        • 1970-01-01
        • 2020-09-20
        • 1970-01-01
        • 2019-02-25
        • 2020-09-25
        • 1970-01-01
        • 2017-06-17
        相关资源
        最近更新 更多