当MySubClass扩展MyClass时,使用在MyClass中返回MyClass对象的方法

时间:2016-12-20 10:26:08

标签: java subclass extends

我很难继承一个非常简单的类,它有返回初始类的方法。

WDS.sampleResult.sampleStart()
WDS.browser.get('http://jmeter-plugins.org')

var jmeterLogo = WDS.browser.findElement(org.openqa.selenium.By.xpath("//img[@alt='Apache JMeter']"))

var actions = new org.openqa.selenium.interactions.Actions(WDS.browser)
actions.moveToElement(jmeterLogo).doubleClick().perform()

WDS.sampleResult.sampleEnd()

好的,现在如果我想打个电话:

public class MyClass {

   public MyClass(){
     }

   public MyClass filterOn(String something){
       MyClass result=new MyClass();
       result.doSomethingUsingThisInstance(this, something);

      return result;
   }

}


 public class MySubClass extends MyClass{
   ....
 }

然后我有一个 java.lang.ClassCastException:无法将MyClass转换为MySubClass

如何防止这种情况?

4 个答案:

答案 0 :(得分:2)

重写filterOn()方法以在MySubClass中创建您想要的实例:

 public class MySubClass extends MyClass{

    public MyClass filterOn(String something){
       MySubClass result = new MySubClass();
       result.doSomethingUsingThisInstance(this, something);
       return result;
    }
   ....
 }

您还可以通过在filterOn()中引入一个方法来创建我们在子类中重写的当前类的实例,从而避免MyClass方法中的重复:

public class MyClass {

   public MyClass(){
     }

   public MyClass createSpecificInstance() {
     return new MyClass();
   }

   public MyClass filterOn(String something){
       MyClass result = createSpecificInstance();
       result.doSomethingUsingThisInstance(this, something);

      return result;
   }

}

现在Sub类只覆盖createSpecificInstance():

public class MySubClass  extends MyClass {

   public MyClass createSpecificInstance() {
     return new MySubClass();
   }

}

答案 1 :(得分:0)

(MySubClass)subClass.filterOn("Hello World");

public MyClass filterOn(String something)

您无法将基类强制转换为派生类。如果你这样做,你会得到那个例外, ClassCastException

阅读本文:java.lang.ClassCastException

答案 2 :(得分:0)

您尝试将返回值强制转换为派生类型,该类型不起作用并导致类强制转换异常。

原因:在类型层次结构中向上强制转换是有效的,因为您的基类只需要派生类(通常)具有的属性/方法。反过来不起作用,因为它可能导致问题。考虑:

class Base {
// some stuff here
}

class Derived1 extends Base {
  private int foo;
}

class Derived2 extends Base {
  private String bar;
}

Base myObject = new Derived1(); 
// this works, Derived1 has everything Base requires
// myObject.foo still exists, but can not be trivially accessed.

Derived2 myOtherObject = (Derived2)myObject;
// Now what? 
// What happens to myObject.foo? 
// Where does myOtherObject.bar come from?

在您的情况下,您可以做些什么:

  • 如果filterOn()的实现根据派生类的具体实现而有很大差异,请在基类中将其设为 abstract ,并在派生类中重新实现它。 / LI>
  • 检查您是否有设计问题。你真的需要将filterOn()的结果转换为派生类吗?
  • 使用Generics。请记住,您可以在基类中使用派生类作为通用类。这仅适用于每个子类filterOn()的实现完全相同(当然类型除外)。
  • 提供允许从基类创建派生类实例的构造函数。使用它而不是演员表。
  • 中的某些内容
Derived1(Base baseObject){
  // copy all the stuff from the base object
  this.foo = 0; // initialize the rest
}
  • 也许继承不是你需要的。组合具有很大程度上击败遗传的倾向(Explained nicely here)。所以你可以尝试:
class BetterThenDerived {
  private Base myBaseObject;
  private int foo;
}

答案 3 :(得分:0)

这是协方差问题的一个方面。请参阅示例Covariance and contravariance。并且Demonstrate covariance and contravariance in Java?。这不是Java擅长的地方,但有几个选择。

首先,在覆盖方法时,您可以声明更具体的返回类型。例如,在MySubClass中,您可以声明:

@Override
public MySubClass filterOn(String something) {
    // ...
}

现在这不能解决您的问题。您仍然需要一种方法来为此方法创建并对MySubClass对象执行某些操作。它做了什么,它使客户端代码免于需要演员表。您可以从davidxxx的答案中获取方法的实现(假设result.doSomethingUsingThisInstance()protectedpublic):

@Override
public MySubClass filterOn(String something) {
    MySubClass result = new MySubClass();
    result.doSomethingUsingThisInstance(this, something);
    return result;
}

您可能不得不在所有子类中复制此方法。如果真实工作留在result.doSomethingUsingThisInstance(),我认为你可以忍受它。

另一个想法是clone()用于生成正确运行时类型的对象:

public class MyClass implements Cloneable {

    public MyClass filterOn(String something) {
        try {
            MyClass result = (MyClass) this.clone();
            result.doSomethingUsingThisInstance(this, something);

            return result;
        } catch (CloneNotSupportedException cnse) {
            throw new AssertionError(cnse);
        }
    }

}
但是,在使用这个想法之前,我会三思而后行。您的克隆包含您不希望存在的数据的一个原因,因此您可能必须确保在克隆之前清除它。您仍然可以将它与返回子类中的特定子类型结合起来,现在它只需要一个强制转换(仍然在实现中,客户端不需要担心):

public class MySubClass extends MyClass {

    @Override
    public MySubClass filterOn(String something) {
        return (MySubClass) super.filterOn(something);
    }

}