Java 当我从抽象超类活动的子类调用方法时发生了什么?

Java 当我从抽象超类活动的子类调用方法时发生了什么?,java,android,inheritance,casting,Java,Android,Inheritance,Casting,我想从我的超类(扩展活动)中调用一个子类函数。但是,我找不到子类的实例,所以我只是天真地尝试降级我的抽象超类,并调用它的方法来查看会发生什么。我没想到这会起作用——超类怎么知道在哪个实例上调用该方法呢 public abstract class RootActivity extends Activity{ private flag someCondition; @Override protected void onCreate(Bundle savedInstance

我想从我的超类(扩展活动)中调用一个子类函数。但是,我找不到子类的实例,所以我只是天真地尝试降级我的抽象超类,并调用它的方法来查看会发生什么。我没想到这会起作用——超类怎么知道在哪个实例上调用该方法呢

public abstract class RootActivity extends Activity{
    private flag someCondition;

    @Override 
    protected void onCreate(Bundle savedInstanceState){ 
        //... 
    }
    // ... 

    public void startJob(JobAction.Id jobaction){
        Log.d("Zlatan", "started a job");
        if (!jobaction.someCondition){
            return;
        }else{
            ((SpecificJob) this).dontDelete(); //<--- What have I done?
            startSomeLongAsynchronousJob(someCondition);
            Log.d("Zlatan", "calling finish");
            finish();
        }

    }
    // ...
    public void someOtherFunction(){
        finish();
    }
    @Override 
    public boolean onKeyDown(int keyCode, KeyEvent event){
        //...
        startJob(JobAction.SOMEENUM);  //Startjob is being called in the superclass
    }
}
}
我没有看到我在SpecificJob.dontDelete()中写的日志。我的问题是

1) 这在运行时做了什么?为什么我看不到“我设置了标志”,为什么它没有崩溃


2) 如何从RootActivity调用SpecificJob中的函数才能达到最佳效果?

在运行时之前,强制转换都是取消选中的,并且当您从RootActivity继承SpecificJob并仅在SpecificJob上调用startJob()时,生成的对象仍然是SpecificJob类型。这意味着有可能使演员没有问题。如果您要扩展RootActivity并尝试在这个新类上调用startJob(),它将无法工作

您不应该从超类调用子类。超类不应该知道它是如何被扩展的。也许有更好的方法,你为什么要这样做

更新:所以把所有将由RootActivity使用的清理代码和任何继承它的类放在RootActivity的onDestroy方法中

public abstract class RootActivity extends Activity{
    @Override 
    public void onDestroy(){
        // All cleanup code common to inherited classes goes here
    }
}
然后在SpecificJob中调用super.ondestory,然后调用SpecificJob特有的任何代码

public class SpecificJob extends SomeClassThatExtendsRootActivity{
    @Override 
    public void onDestroy(){
        super.onDestroy();
        // All cleanup code unique to this class goes here
    }    

}

如前所述,这是有效的,因为对象“知道”其类型,并且类型转换仅在运行时检查。因此,如果在
SpecificJob
实例上调用
startJob()
,它将工作。但是,如果在另一个
RootActivity
子类的实例上调用该方法,则在运行时会出现异常。这也是您应该尽可能避免类型转换的原因

在这种特殊情况下,很容易以类型安全的方式编写代码。只需将方法
dontDelete()
的声明添加到
RootActivity
,如下所示

protected abstract void dontDelete();

这将强制具体的子类实现该方法,并使类型转换变得不必要。

在哪里调用startJob?startJob在RootActivity的多个位置调用,在覆盖函数(如OnOptions ItemSelected和onKeyDown)中。这是我问题的一部分;我知道我应该在SpecificJob类中拦截这些,但我知道有很多。我在SpecificJob的onDestroy中做了一些清理,。但是,我的清理代码中的一个条件取决于活动关闭是由RootActivity.startJob(…)中使用的finish导致的,还是通过其他方式导致的。我的解决方案是1)在RootActivity中设置一个标志,并在SpecificJob中获取它,这是我不想做的,或者2)拦截对startJob的每次调用,这只是一堆代码,或者3)在RootActivity中调用一个函数来提醒SpecificJob,这就是我在这里尝试过的。@EricS。如果清理取决于使用哪个类(例如RootActivity/SpecificJob/SomeClassThatExtendedRootActivity),那么您应该将代码分别放在每个类中,然后调用超类的方法。我会更新我的答案。谢谢@mbdavis。我的清理代码实际上是发送一个广播到其他地方,而不是真正的“清理”-我想这是一个用词不当。考虑到我所看到的庞然大物,它可能不会起作用,但无论如何还是要感谢你。@EricS。广播是如何产生的?这仍然是正确使用继承的途径——可能需要重新思考我对它使用哪个特定作业实例感到困惑,以及为什么没有运行SpecificJob中的行。我并没有指定一个实例,我想可能有一些神奇的事情发生了,因为SpecificJob是作为单任务活动启动的。它是否使用了抽象RootActivity的实例?每个
SpecificJob
实例也是
RootActivity
实例。这就是继承的工作原理:)
public class SpecificJob extends SomeClassThatExtendsRootActivity{
    @Override 
    public void onDestroy(){
        super.onDestroy();
        // All cleanup code unique to this class goes here
    }    
protected abstract void dontDelete();