简体   繁体   English

将Object转换为最低级别

[英]Casting an Object to its lowest class

Is there a way to cast an Object to its "lowest" class? 有没有办法将对象强制转换为“最低”类? In my case, "Arc" and "Line" extend "Curve". 在我的例子中,“弧形”和“线条”延伸“曲线”。 I want to save both in an ArrayList and then do something with them, depending on what class it is. 我想将它们保存在ArrayList中,然后根据它们的类来对它们执行某些操作。 This example outputs "curve", "curve" but I want it to be "arc", "line". 这个例子输出“曲线”,“曲线”,但我希望它是“弧”,“线”。 Thanks for your help! 谢谢你的帮助!

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

EDIT: Thank you for your answers! 编辑:谢谢你的答案! It works so far, but my problem is a little more complicated. 它到目前为止工作,但我的问题有点复杂。 What I want to do is find the intersection Point(s) of two geometrical Objects (so Line - Arc, Line - Line, Line - Circle etc.) 我想要做的是找到两个几何对象的交点(所以线 - 弧,线 - 线,线 - 圆等)

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
}
}

I want to access these methods with Curve objects, so in abstract class Curve there is a method intersection (Curve) . 我想用Curve对象访问这些方法,所以在abstract class Curve有一个方法intersection (Curve) When I call this method it returns an empty Array, because it called the method from Curve class. 当我调用此方法时,它返回一个空数组,因为它从Curve类调用了该方法。 How can I tell Java to use the methods from classes Arc, Line etc and not from Curve? 如何告诉Java使用Arc,Line等类中的方法而不是Curve中的方法?

public abstract class Curve {

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

Method overloading is resolved during compilation, based on the static type of the parameters passed to the method, therefore, when you pass a variable of type Curve , the method static void test(Curve c) is always chosen, regardless of the runtime type of the objects referenced by the variable i . 根据传递给方法的参数的静态类型,在编译期间解析方法重载,因此,当您传递Curve类型的变量时,始终选择方法static void test(Curve c) ,而不管运行时类型如何变量i引用的对象。

You can replace your static test methods with instance methods, and thus use method overriding: 您可以使用实例方法替换静态test方法,从而使用方法覆盖:

In Line class: 在Line类中:

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

In Arc class: 在Arc类中:

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

In Curve class: 在Curve类中:

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

And change your loop to 并将你的循环改为

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

That's the most common design error you are making there. 这是你在那里最常见的设计错误。

As @Eran said you shall move the logic from global handler into the class instances. 正如@Eran所说,你应该将逻辑从全局处理程序移动到类实例中。

The problem can be specified in another way: 可以用另一种方式指定问题:

You cast object like Arc and Line to its more generic form - Curve 您将ArcLine类的对象转换为更通用的形式 - Curve

And then try to differentiate between Arc and Line objects. 然后尝试区分ArcLine对象。

  • For Arc s output message that the object is Arc 对于Arc s输出消息,该对象为Arc
  • For Line s output message that the object is Line 对于Line s输出消息,该对象为Line

To differentiate the object classes you must use Java mechanisms: 要区分对象类, 必须使用Java机制:

  • Execute its method (methods of objects are the best way to determine the type of object) 执行其方法(对象的方法是确定对象类型的最佳方法)

  • Use instenaceof operator 使用instenaceof运营商

So the best, proffesional approach is to implement methods test in each of the classes: 因此,最好的专业方法是在每个类中实现方法test

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

It's not advised to use instanceof because it generate bugs and you can write a code like this one: 不建议使用instanceof因为它会生成错误,您可以编写如下代码:

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

In that case if you add new class like OtherGeometricalObject you may forget to change implementation of test to add line: 在这种情况下,如果添加像OtherGeometricalObject这样的新类,您可能会忘记更改test实现以添加行:

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

That's why instanceof is in most cases a really bad deal and should be avoided! 这就是为什么在大多数情况下, instanceof是一个非常糟糕的交易 ,应该避免!

If you would like to differentiate between objects like in the example (do something for objects of one class and something other for other classes objects) just use class method! 如果你想区分对象中的对象(对一个类的对象做一些事情,对其他类对象做一些其他的事情),只需使用类方法!

It's the mechnism designed for that purpose! 这是为此目的而设计的机制!

I hope my explanation is rich and helpful :) 我希望我的解释是丰富和有用的:)

You want to get a OOP behavior for each subclass where the behavior depends on the runtime class but overloading with a static modifier will not allow that. 您希望为每个子类获取OOP行为,其中行为依赖于运行时类,但使用static修饰符进行重载将不允许这样做。
The selection of the method being done at compile time according to the declared type of the argument. 根据声明的参数类型在编译时选择方法。

As Eran suggested, let each subclass defines its test() method and invoke the method on an instance of it. 正如Eran建议的那样,让每个子类定义其test()方法并在其实例上调用该方法。

Besides, what you want can be performed with an Object method. 此外,您可以使用Object方法执行所需的操作。
The method toString() is designed for returning a String representing of the object. toString()方法用于返回表示对象的String。

You can directly use it in this way : 您可以通过以下方式直接使用它:

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

If the default toString() method doesn't suit for you, you may override it in subclasses. 如果默认的toString()方法不适合您,您可以在子类中覆盖它。

In Line class : 在Line类中:

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

In Arc class: 在Arc类中:

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

In Curve class: 在Curve类中:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM