【问题标题】:Casting an Object to its lowest class将对象转换为最低类
【发布时间】:2017-10-22 12:49:41
【问题描述】:

有没有办法将一个对象转换为它的“最低”类?就我而言,“弧”和“线”扩展了“曲线”。我想将两者都保存在一个 ArrayList 中,然后对它们做一些事情,这取决于它是什么类。这个例子输出“曲线”,“曲线”,但我希望它是“弧”,“线”。感谢您的帮助!

public class Test4 {

public static void main(String[] args) {
    ArrayList<Curve> curves = new ArrayList<>();
    Arc arc = new Arc(new Point(0, 0, 0), 0, 0, 0);
    Line line = new Line(new Point(0, 0, 0), new Point(1, 0, 0));
    curves.add(arc);
    curves.add(line);

    for (Curve i : curves) {
        test(i);
    }
}

public static void test(Line l) {
    System.out.println("line");
}

public static void test(Arc a) {
    System.out.println("arc");
}

public static void test(Curve c) {
    System.out.println("curve");
}
}

编辑:感谢您的回答!到目前为止它有效,但我的问题有点复杂。我想要做的是找到两个几何对象的交点(所以线 - 弧,线 - 线,线 - 圆等)

public class Line{
    //constructor and other methods
public Point[] intersection(Circle circle) {
    //some code
}

public Point[] intersection(Line line) {
    //some code
}

public Point[] intersection(LineSeg s) {
    //some code
}
}

我想用Curve 对象访问这些方法,所以在abstract class Curve 中有一个方法intersection (Curve)。当我调用此方法时,它返回一个空数组,因为它从Curve 类中调用了该方法。如何告诉 Java 使用 Arc、Line 等类中的方法而不是 Curve 中的方法?

public abstract class Curve {

public Point[] intersection(Curve c) {
    return new Point[] {};
}
}

【问题讨论】:

    标签: java


    【解决方案1】:

    方法重载在编译期间根据传递给方法的参数的静态类型来解决,因此,当您传递Curve类型的变量时,始终选择方法static void test(Curve c),而不管运行时类型如何变量i引用的对象。

    您可以用实例方法替换您的静态 test 方法,从而使用方法覆盖:

    在 Line 类中:

    public void test() {
        System.out.println("line");
    }
    

    在 Arc 类中:

    public void test() {
        System.out.println("arc");
    }
    

    在曲线类中:

    public void test() {
        System.out.println("curve");
    }
    

    然后将循环更改为

    for (Curve i : curves) {
        i.test();
    }
    

    【讨论】:

      【解决方案2】:

      这是您最常犯的设计错误。

      正如@Eran 所说,您应该将逻辑从全局处理程序移动到类实例中。

      问题可以用另一种方式指定:

      您将 ArcLine 之类的对象转换为更通用的形式 - Curve

      然后尝试区分 ArcLine 对象。

      • 对于Arcs 输出消息,对象为Arc
      • 对于Lines 输出消息,对象为Line

      要区分对象类,您必须使用 Java 机制:

      • 执行其方法(对象的方法是判断对象类型的最佳方式)

      • 使用instenaceof运算符

      所以最好的、专业的方法是在每个类中实现方法test

       public void test() {
           System.out.println("Your type");
       }
      

      不建议使用instanceof,因为它会产生错误,您可以编写这样的代码:

      public static void test(Curve c) {
          if(c instanceof Arc) {
               System.out.println("Arc");
               return;
          }
          System.out.println("Something else");
      }
      

      在这种情况下,如果您添加像 OtherGeometricalObject 这样的新类,您可能会忘记更改 test 的实现以添加行:

          if(c instanceof OtherGeometricalObject) {
               System.out.println("OtherGeometricalObject");
               return;
          }
      

      这就是为什么instanceof 在大多数情况下是非常糟糕的交易,应该避免!

      如果您想区分示例中的对象 (为一个类的对象做一些事情,为其他类的对象做一些事情) 只需使用类方法!

      这是为此目的而设计的机制!

      我希望我的解释丰富而有帮助:)

      【讨论】:

        【解决方案3】:

        您希望获得每个子类的 OOP 行为,其中行为取决于运行时类,但使用 static 修饰符重载将不允许这样做。
        在编译时根据参数声明的类型选择方法。

        按照 Eran 的建议,让每个子类定义其 test() 方法并在其实例上调用该方法。

        此外,您可以使用Object 方法执行您想要的操作。
        方法toString() 旨在返回表示对象的字符串。

        你可以这样直接使用:

        for (Curve curve : curves) {
           System.out.println(curve);
        }
        

        如果默认的toString() 方法不适合您,您可以 在子类中覆盖它。

        在线类:

        public String toString() {
            return "line";
        }
        

        在 Arc 类中:

        public String toString() {
            return "arc";
        }
        

        在曲线类中:

        public String toString() {
            return "curve";
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-27
          • 2018-04-13
          • 1970-01-01
          • 1970-01-01
          • 2022-09-29
          • 1970-01-01
          相关资源
          最近更新 更多