检查调用对象是否为子类的实例

时间:2011-07-22 20:01:05

标签: java oop inheritance polymorphism

我有2节课。我们称它们为A类和B类.A类包含一个执行某些动作的方法。 B类使用自己的版本覆盖此方法,但会在A类中对该方法进行super调用以执行操作。现在,这工作正常。但是,如果对象一个类A的实例,那么只有在A类中才会执行一些操作。换句话说,如果对象是,则不应该在A类方法中执行某些操作。 A类儿童的一个实例。

目前,我正在使用instanceof来检查每个孩子,但我需要指定每个子类,因此如果以后添加新子项,则需要更新此方法。我想要的是一种确定对象是否是子类的动态方法。

有没有好的选择,或者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
   }
}

正如对设计的解释一样,我用它来生成XML。在程序中,我有List<A>来存储数据。当需要输出XML时,我遍历列表并调用generateXMLsomeMethod在我的示例中占据了它的位置。)

创建A类对象时,需要将其数据放在<A></A>个标记内。创建B类对象时,需要将其数据放在<B></B>个标记内。但A的所有属性也必须位于<B></B>标记内,因此现在它调用的对象只有generateXML对象时使用的A方法}

但正如其他人所指出的那样,调用同样的方法并不是可行的方法。类B应该在类A中调用受保护的方法,该方法仅生成必要的信息。

8 个答案:

答案 0 :(得分:7)

创建执行特定于类的事物的受保护方法,并从someMethod()调用它们。 A类将提供其实现,如果子类需要有效地删除该代码,那么它可以使用空实现覆盖受保护的方法。

不要对抗多态性;使用它对你有利。

示例:

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

答案 1 :(得分:3)

那么现在这是一个可怕的设计,应该以不同的方式解决(例如,让从子类调用的部分成为一个自己的受保护方法),但如果你真的需要它,你可以检查

this.getClass()== A.class以查看该类是否真的相同。

答案 2 :(得分:1)

我认为instanceof是一个使用多态的机会。

保持所有类型someMethod的{​​{1}}共同行为。子类A用于实现您当前使用A检查的行为。

instanecof

答案 3 :(得分:1)

为什么不:

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

public class B extends A{

    @Override
   public void someMethod(){

       super.someMethod();

       // More actions
   }
}

答案 4 :(得分:1)

这可能与cdhowie试图说的相同。 (没有冒犯:我认为你有点不清楚。)

不要使用instanceof。而是创建返回给定类型的标志或其他适当值的方法。

你的例子没有提供你想要做什么的任何细节,所以我只是发明了一些东西。

!!!错误的方式!!!

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

更好的方式:

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

这样,超类不必知道子类需要什么。每个子类定义自己的行为。在这种情况下,每个子类定义一个isManualTransmission函数,并在适当时返回true或false。

更好的是避免使用标志并在每个类中放置适当的行为:

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

答案 5 :(得分:0)

只有当这是A类的实例时,表达式A.class.equals(this.getClass())才返回true。如果是子实例,则结果将为false。

但是:如果你必须这样做,请检查你的设计。听起来非常不是面向对象的风格。我可以给你一个替代方案。将基类A分为2:真正的基类A0及其子A1。你的B级将是A1的兄弟,并将直接从A0延伸。

在这种情况下,您可以将公共代码放入A0类,并将所有特定代码(在您的版本中必须仅在类完全是A而不是其子类时执行)到A1。

答案 6 :(得分:0)

我可能会弄错,但你的情况似乎是“赞成合成而不是继承”和“封装不同的东西”的理想场景。在像你这样的情况下,一般的行动方针是:

  1. 没有子类从超类扩展
  2. 隔离私有方法中应该只属于A的代码部分。
  3. 在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();
        }
    }
    
  4. 同样,我可能错了,这可能不适用于你的情况。

答案 7 :(得分:0)

“call super”is an anti-pattern。而不是期望子类调用超类功能,而是反过来。现在,超类完全控制了“普通”之前和之后所谓的内容。

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