java 检查调用对象是否是子类的实例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6795442/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Check if Calling Object is Instance of Child Class
提问by compuguru
I have 2 classes. Let's call them class A and class B. Class A contains a method that executes some action. Class B overrides this method with its own version, but does make a super
call to that method in class A to perform an action. Right now, this is working fine. However, there are some actions in class A that should only be executed if the object is onlyan instance of class A. Put another way, some actions in the Class A method should not happen if the object is an instance of a child of Class A.
我有2节课。让我们称它们为类 A 和类 B。类 A 包含一个执行某些操作的方法。B 类用它自己的版本覆盖了这个方法,但会super
调用 A 类中的那个方法来执行一个操作。现在,这工作正常。但是,类 A 中的某些操作仅应在对象只是类 A 的实例时才执行。换句话说,如果对象是类的子项的实例,则不应发生类 A 方法中的某些操作一个。
Currently, I'm using instanceof
to check for each child, but I need to specify each child class, so if a new child is added at a later date, this method needs to be updated. What I would like is a dynamic way of determining if the object is a child class.
目前,我正在使用instanceof
检查每个孩子,但我需要指定每个孩子类,因此如果以后添加新孩子,则需要更新此方法。我想要的是一种确定对象是否为子类的动态方法。
Are there any good alternatives, or is instanceof
the way to go?
有没有好的选择,或者是instanceof
要走的路?
public class A{
public void someMethod(){
// Only perform these actions if it is not a child class. This is what
// I am looking for a better solution for
if(!(this instanceof B)){
// Some action...
}
// Actions to execute for every call
}
}
public class B extends A{
@Override
public void someMethod(){
super.someMethod();
// More actions
}
}
Just as an explanation of the design, I am using it to generate XML. In the program, I have a List<A>
to store the data. When it is time to output the XML, I loop through the list and call generateXML
(the someMethod
takes its places in my example).
作为设计的解释,我使用它来生成 XML。在程序中,我有一个List<A>
来存储数据。当需要输出 XML 时,我会遍历列表并调用generateXML
(someMethod
在我的示例中使用它)。
When an object of class A is created, it needs to have its data within <A></A>
tags. When an object of class B is created, it needs to have its data within <B></B>
tags. But all the properties of A
must also be inside the <B></B>
tags, so as of right now it calls the same generateXML
method used when an object is only of of Class A
当创建类 A 的对象时,它需要在<A></A>
标签中包含其数据。当创建类 B 的对象时,它需要在<B></B>
标签中包含其数据。但是 的所有属性A
也必须在<B></B>
标签内,所以现在它调用的generateXML
方法与对象仅属于 Class 时使用的方法相同A
But as some others have pointed out, calling that same method isn't the way to go. Class B
should be calling a protected method in class A
that only generates the necessary information.
但正如其他一些人指出的那样,调用相同的方法并不是要走的路。类B
应该调用A
只生成必要信息的类中的受保护方法。
回答by cdhowie
Create protected methods that do the class-specific things, and call them from someMethod(). Class A will provide its implementation, and if a subclass needs to effectively remove that code, then it can override the protected method with an empty implementation.
创建执行特定于类的事情的受保护方法,并从 someMethod() 调用它们。类 A 将提供其实现,如果子类需要有效地删除该代码,则它可以使用空实现覆盖受保护的方法。
Don't fight polymorphism; use it to your advantage.
不要与多态性作斗争;充分利用它。
Example:
例子:
public class A {
protected void someOtherMethod() {
// Do stuff specific to A here.
}
public void someMethod() {
// Do some stuff
someOtherMethod();
// Do some more stuff
}
}
public class B extends A {
@Override
protected void someOtherMethod() {
// Empty implementation; B doesn't need to do this.
// Or do stuff specific to B...
}
}
回答by Voo
Well now that's a horrible design and should be solved in a different way (eg make the part that is called from the subclass a own protected method), but alas if you really need it you can check for
那么现在这是一个可怕的设计,应该以不同的方式解决(例如,使从子类调用的部分成为自己的受保护方法),但是唉,如果您真的需要它,您可以检查
this.getClass() == A.class to see if the class is really identical.
this.getClass() == A.class 以查看类是否真的相同。
回答by Jay
This may be the same as what cdhowie was trying to say. (No offense: I thought you were a little unclear.)
这可能和 cdhowie 想说的一样。(无意冒犯:我以为你有点不清楚。)
Don't use instanceof. Instead, create methods that return flags or other appropriate values for the given type.
不要使用 instanceof。相反,创建为给定类型返回标志或其他适当值的方法。
Your example doesn't give any details of what you're trying to do, so I'll just invent something.
你的例子没有给出你想要做什么的任何细节,所以我会发明一些东西。
!!! Wrong way !!!
!!!错误的方法 !!!
public class Car
{
public void goUphill()
{
// XYZ has automatic transmission -- don't need to downshift
if (!(this instanceof XYZ())
{
downshift();
}
pressGas();
}
}
public class ModelXYZCar extends Car
{
public void goUphill()
{
tellWifeToGetOutAndPush();
super.goUphill();
}
}
Better way:
更好的方法:
public class Car
{
public boolean isManualTransmission()
{
// default
return true;
}
public void goUphill()
{
if (isManualTransmission())
{
downshift();
}
pressGas();
}
}
public class ModelXYZCar extends Car
{
public boolean isManualTransmission()
{
return false;
}
public void goUphill()
{
tellWifeToGetOutAndPush();
super.goUphill();
}
}
This way, the super class doesn't have to know what the subclasses need. Each subclass defines its own behavior. In this case, each subclass defines an isManualTransmission function and returns true or false as appropriate.
这样,超类就不必知道子类需要什么。每个子类都定义了自己的行为。在这种情况下,每个子类都定义了一个 isManualTransmission 函数并根据需要返回 true 或 false。
Better still is to avoid the need for flags and put the appropriate behavior in each class:
更好的是避免使用标志并将适当的行为放在每个类中:
abstract public class Car
{
abstract public void downshift();
public void goUphill()
{
downshift();
pressGas();
}
}
public class AutomaticTransmissionCar extends Car
{
public void downshift()
{
// Automatic transmission -- no need to do anything
}
}
public class ManualTransmissionCar extends Car
{
public void downshift()
{
... whatever ...
}
}
public class ModelXYZCar extends ManualTransmissionCar
{
public void goUphill()
{
tellWifeToGetOutAndPush();
super.goUphill();
}
}
回答by Jonathon Faust
I see instanceof
as an opportunity to use polymorphism.
我认为这instanceof
是一个使用多态的机会。
Keep behavior in someMethod
common to all types of A
. Subclass A
to implement behavior you're currently checking for with the instanecof
.
保持someMethod
所有类型的共同行为A
。子类A
来实现你目前检查与行为instanecof
。
public class A{
public void someMethod(){
// Get rid of the special section and put it in it's own class
// Keep only agnostic behavior common to all types of A
// Actions to execute for every call
}
}
public class B extends A{
@Override
public void someMethod(){
super.someMethod();
// More actions
}
}
public class C extends A{
@Override
public void someMethod(){
super.someMethod();
// Actions that were originally in the if(instanceof) check
}
}
回答by emory
Why not:
为什么不:
public class A{
public void someMethod(){
// Only perform these actions if it is not a child class. This is what
// I am looking for a better solution for
if(this.getClass().equals(A.class))
// Some action...
}
// Actions to execute for every call
}
}
And
和
public class B extends A{
@Override
public void someMethod(){
super.someMethod();
// More actions
}
}
回答by AlexR
Expression A.class.equals(this.getClass())
returns true only if this is really the instance of class A. If it is child instance the result will be false.
A.class.equals(this.getClass())
仅当这确实是类 A 的实例时,表达式才返回 true。如果它是子实例,则结果将为 false。
BUT: if you have to do this check your design. It sounds very not object oriented style. I can give you an alternative. Separate your base class A onto 2: the really base class A0 and its child A1. Your class B will be the brother of A1 and will extend directly from A0.
但是:如果您必须这样做,请检查您的设计。这听起来很不是面向对象的风格。我可以给你一个替代方案。将您的基类 A 分成 2 个:真正的基类 A0 及其子类 A1。您的 B 类将是 A1 的兄弟,并将直接从 A0 扩展。
In this case you can put the common code into class A0 and all specific code (that in your version must be executed only if the class is exactly A and not its subclass) to A1.
在这种情况下,您可以将公共代码放入 A0 类,并将所有特定代码(只有当类恰好是 A 而不是它的子类时才必须执行您的版本中的代码)到 A1。
回答by Jeshurun
I could be mistaken, but your case seems like the ideal scenario to "favour composition over inheritance" and "encapsulate what varies". One general course of action in a situation like yours is to:
我可能弄错了,但您的情况似乎是“偏爱组合而不是继承”和“封装变化的内容”的理想场景。在像您这样的情况下,一个一般的行动方针是:
- Not have your subclasses extend from the superclass
- Isolate the section of code that should only belong to A in a private method.
Create an instance of A in B, C, etc and call A.someMethod().
public class A { public void someMethod(){} private void someOtherMethod(){ // move behavior specific to A in here. } } public class B { // no extends public void someMethod() { new A().someMethod(); } }
- 没有您的子类从超类扩展
- 在私有方法中隔离应该只属于 A 的代码部分。
在 B、C 等中创建 A 的实例并调用 A.someMethod()。
public class A { public void someMethod(){} private void someOtherMethod(){ // move behavior specific to A in here. } } public class B { // no extends public void someMethod() { new A().someMethod(); } }
Again, I could be wrong and this might not apply to your case.
同样,我可能是错的,这可能不适用于您的情况。
回答by Karl Knechtel
"call super" is an anti-pattern. Instead of expecting the subclass to invoke superclass functionality, turn it the other way around. Now the superclass has complete control of what's called both before and after the "common" stuff.
“调用超级”是一种反模式。与其期望子类调用超类功能,不如反过来。现在超类可以完全控制在“普通”东西之前和之后的东西。
public class A {
public void someMethod() {
beforeCommonStuff();
// Actions to execute for every call
afterCommonStuff();
}
protected void beforeCommonStuff() {
// Actions to execute only for class A
}
protected void afterCommonStuff() {}
}
public class B extends A {
@Override
protected void afterCommonStuff(){
// More actions
}
}