繁体   English   中英

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

[英]What happened when I called a method from a subclass from the abstract superclass activity?

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

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

我这里有一个子类。 该活动是由另一个活动启动的,我在此处也包含了清单片段。

public class SpecificJob extends SomeClassThatExtendsRootActivity{
    //SomeClassThatExtendsRootActivity extends RootActivity - I've ommitted it
    private boolean flag = false;
    @Override
    public void onCreate(Bundle bundle){
        super.onCreate(bundle);
        //...
    }
    // ... some code ...
    public void dontDelete(){ //Not static
        flag = true;
        Log.d("Zlatan", "I set flag"); //This doesn't appear in log
    }

    @Override 
    public void onDestroy(){
        Log.d("Zlatan", "When finishing, flag is now " + flag);
    }
}

<activity
        android:name=".SpecificJob"
        android:label="@string/TXT_BOOKMARKS"
        android:icon="@drawable/ic_launcher"
        android:theme="@style/stuff"
        android:launchMode="singleTask"
        android:windowSoftInputMode="stateHidden"
        android:taskAffinity=".SpecificJob">
        <intent-filter>
            <action android:name="com.me.feature.SOME_WORKFLOW" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        <meta-data
            android:name="concurrency"
            android:value="DEFAULT_CONCURRENCES|printer"
            />
    </activity>

令我惊讶的是,没有错误或崩溃。 我的结果是

D/Zlatan started a job
D/Zlatan calling finish
D/Zlatan﹕ When finishing, flag is now false

我看不到我在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.onDestroy,然后调用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()添加方法dontDelete()RootActivity ,就像这样

protected abstract void dontDelete();

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

暂无
暂无

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

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