识别扩展类对象

时间:2012-12-14 18:07:32

标签: java

在Java中,我有一个类Num,以及一些扩展Num的类,如Num_intNum_double。 我想知道方法是否可以识别给定的Num对象是否为Num_int

我有以下代码:

void test(Num_int x) {
  System.out.println("int");
} // test
void test(Num x) {
  System.out.println("other");
} // test

Num_int A = new Num_int( );
Num B     = new Num_int( );
Num C     = new Num_double( );

test(A); // prints "int"
test(B); // prints "other"
test(C); // prints "other"

不幸的是,当给出A作为参数时,方法“test”仅打印“int”。 当B通过时,我还不能打印“int”,因为B是通过Num B = new Num_int( );创建的。这可能吗?

感谢。

5 个答案:

答案 0 :(得分:3)

if (x instanceof Num_int) {
  System.out.println("int");
} else {
  System.out.println("other");
}

答案 1 :(得分:3)

如果您想要多态行为,那么使测试方法成为Num类的可覆盖方法。

根据参数的运行时类型,不会以多态方式解析重载方法。它们在编译时根据声明的参数类型得到解决。

答案 2 :(得分:2)

这可以使用instanceof运算符和强制转换来完成。但是,这是一种糟糕的编程习惯。

更好的选择是让test()成为final的非Num成员,并在每个类中适当地覆盖它。然后你只需要调用A.test(),Java的动态调度将为你处理一切。

public class Num {
  public void test() {
    System.out.println("other");
  }
}

public class Num_int extends Num {
  public void test() {
    System.out.println("int");
  }
}

public class Num_double extends Num {
  // inhertis Num.test()
}

答案 3 :(得分:1)

问题是方法签名在Java编译时被绑定,因此声明的类型决定了调用哪个方法。

参见书籍Java Puzzlers中的益智游戏“制作一个哈希”。

您可以使用双重调度和访客模式。它看起来像这样:

Num_int A = new Num_int( );
Num B     = new Num_int( );
Num C     = new Num_double( );

Num_printer p = new Num_printer();

A.accept(p);
B.accept(p);
C.accept(p);

Num_int.accept(...)Num_double.accept(...)方法看起来都是这样的:

public class Num_int extends Num {
    public void accept(Num_visitor v) {
        v.visit(this); // from this scope, `this` has a declared type of `Num_int`
                       // so at compile time this is binded to signature visit(Num_double)
    }
}

public class Num_double extends Num {
    public void accept(Num_visitor v) {
        v.visit(this); // from this scope, `this` has a declared type of `Num_double`
                       // so at compile time this is binded to signature visit(Num_double)
    }
}

尽管这些方法几乎完全相同,但重要的是该方法不会被提取到父类中。我甚至在父类中将其抽象化:

public class Num {
    public abstract void accept(Num_visitor);
}

在班级Num内,this声明为Num。如果此处定义了accept方法,则编译时绑定将是签名visit(Num) - 再次为您提供相同的原始问题。

最后,Num_printer看起来像这样:

public class Num_printer implements Num_visitor {

    public void visit(Num_int n) {
        System.out.println("int");
    }

    public void visit(Num_double n) {
        System.out.println("double");
    }

}

答案 4 :(得分:0)

您可以使用instanceof运算符。阅读this document中的“类型比较运算符实例”部分。

if (x instanceof Num_int) {
  // do something
} else if (x instanceof Num_double) {
  // do something else
}