将对象转换为最低类

时间:2017-10-22 12:49:41

标签: java

有没有办法将对象强制转换为"最低"类?就我而言," Arc"和" Line"延伸"曲线"。我想将它们保存在ArrayList中,然后根据它们的类来对它们执行某些操作。这个例子输出"曲线","曲线"但我希望它是" arc"," line"。谢谢你的帮助!

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[] {};
}
}

3 个答案:

答案 0 :(得分:3)

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

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

在Line class中:

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();
}

答案 1 :(得分:1)

这是你在那里最常见的设计错误。

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

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

  

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

     

然后尝试区分ArcLine个对象。

     
      
  • 对于Arc输出消息,对象为Arc
  •   
  • 对于Line输出消息,对象为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在大多数情况下是非常糟糕的交易,应该避免!

如果您想区分示例中的对象 (对一个类的对象执行某些操作,对其他类对象执行其他操作) 只需使用类方法!

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

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

答案 2 :(得分:1)

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

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

此外,您可以使用Object方法执行所需的操作 方法toString()用于返回表示对象的String。

您可以这样直接使用它:

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

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

在Line class中:

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

在Arc类中:

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

在曲线课程中:

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