简体   繁体   English

识别扩展类对象

[英]Recognizing extended class object

In Java, I have a class Num , and a few classes that extend Num , like Num_int and Num_double . 在Java中,我有一个类Num ,以及一些扩展Num类,如Num_intNum_double I want to know whether it's possible for a method to recognize whether a given Num object is a Num_int or not. 我想知道一个方法是否有可能识别给定的Num对象是否是Num_int

I have the following code: 我有以下代码:

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"

Unfortunately, the method "test" only prints "int" when A is given as argument. 不幸的是,当给出A作为参数时,方法“test”仅打印“int”。 I wan't the function to also print "int" when B is passed, since B is created via Num B = new Num_int( ); 当B被传递时,我还不能打印“int”,因为B是通过Num B = new Num_int( ); . Is this possible? 这可能吗?

Thanks. 谢谢。

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

If you want polymorphic behaviour, then make the test method an overridable method of the Num class. 如果您想要多态行为,那么使测试方法成为Num类的可覆盖方法。

Overloaded methods are not resolved polymorphically based on the runtime type of the arguments. 根据参数的运行时类型,不会以多态方式解析重载方法。 They're resolved at compile-time, based on the declared type of the arguments. 它们在编译时根据声明的参数类型得到解决。

This can be done using the instanceof operator and casting. 这可以使用instanceof运算符和强制转换来完成。 However, this is a poor programming practice. 但是,这是一个糟糕的编程习惯。

A better option is to make test() a non- final member of Num , and override it appropriately in each class. 更好的选择是使test()成为Num的非final成员,并在每个类中适当地覆盖它。 Then you just call A.test() , and Java's dynamic dispatch will take care of everything for you. 然后你只需调用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()
}

The problem is that method signatures are binded at compile time in Java, so the declared type determines which method is called. 问题是方法签名在Java编译时被绑定,因此声明的类型决定了调用哪个方法。

See also the puzzler "Making a Hash of It" in the book Java Puzzlers . 另请参阅Java Puzzlers一书中的益智游戏“Make a Hash of It”。

You could use double-dispatching and the Visitor pattern. 您可以使用双重调度和访客模式。 It would look something like this: 它看起来像这样:

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

The Num_int.accept(...) and Num_double.accept(...) methods would both look like this: 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)
    }
}

Even though these methods are almost identical, it's important that the method isn't extracted into the parent class. 尽管这些方法几乎相同,但重要的是该方法不会被提取到父类中。 I'd go so far as to make it abstract in the parent class: 我甚至在父类中使它变得抽象:

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

From within class Num , this is of declared type Num . 在类Numthis是声明的类型Num If the accept method were defined here, the compile-time binding would be to signature visit(Num) - giving you the same original problem all over again. 如果在这里定义了accept方法,那么编译时绑定将是签名visit(Num) - 再次给你相同的原始问题。

Lastly, the Num_printer would look like this: 最后, 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");
    }

}

You can use the instanceof operator. 您可以使用instanceof运算符。 Read the " The Type Comparison Operator instanceof " part in this document . 阅读本文档中的“ 类型比较运算符instanceof ”部分。

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

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

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