Development Tip

파생 클래스가 수퍼 메서드를 호출하도록 강제하는 방법은 무엇입니까?

yourdevel 2020. 10. 17. 12:27
반응형

파생 클래스가 수퍼 메서드를 호출하도록 강제하는 방법은 무엇입니까? (Android처럼)


Activity클래스를 만든 다음 onCreate()메서드 를 재정의 할 때 이클립스에서 항상 자동으로 추가됩니다 super.onCreate(). 어떻게 이런 일이 발생합니까? 이것을 강제하는 추상 또는 부모 클래스에 Java 키워드가 있습니까?

수퍼 클래스를 호출하지 않는 것이 불법인지는 모르겠지만 일부 메서드에서는 이렇게하지 않아 예외가 발생했음을 기억합니다. 이것은 또한 자바에 내장되어 있습니까? 이를 위해 키워드를 사용할 수 있습니까? 아니면 어떻게하나요?


다음 Activity#onCreate()은 거의 모든 주석입니다 ( 원본-~ 800 행 참조 ).

/**
 * Called when the activity is starting.  This is where most initialization
 * should go: calling {@link #setContentView(int)} to inflate the
 * activity's UI, using {@link #findViewById} to programmatically interact
 * with widgets in the UI, calling
 * {@link #managedQuery(android.net.Uri , String[], String, String[], String)} to retrieve
 * cursors for data being displayed, etc.
 *
 * <p>You can call {@link #finish} from within this function, in
 * which case onDestroy() will be immediately called without any of the rest
 * of the activity lifecycle ({@link #onStart}, {@link #onResume},
 * {@link #onPause}, etc) executing.
 *
 * <p><em>Derived classes must call through to the super class's
 * implementation of this method.  If they do not, an exception will be
 * thrown.</em></p>
 *
 * @param savedInstanceState If the activity is being re-initialized after
 *     previously being shut down then this Bundle contains the data it most
 *     recently supplied in {@link #onSaveInstanceState}.  <b><i>Note: Otherwise it is null.</i></b>
 *
 * @see #onStart
 * @see #onSaveInstanceState
 * @see #onRestoreInstanceState
 * @see #onPostCreate
 */
protected void onCreate(Bundle savedInstanceState) {
    mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
            com.android.internal.R.styleable.Window_windowNoDisplay, false);
    mCalled = true;
}

그래서 제 생각에는 ADT Eclipse 플러그인이 그 호출을 자동으로 추가하는 super.onCreate()것입니다. 그래도 완전히 추측입니다.


이것은 지원 주석 라이브러리에 추가됩니다.

dependencies {
    compile 'com.android.support:support-annotations:22.2.0'
}

http://tools.android.com/tech-docs/support-annotations

안녕하세요.


하위 클래스가 부모 클래스의 논리를 실행 하도록 강제 하려는 경우 일반적인 패턴은 다음과 같습니다.

public abstract class SuperClass implements SomeInterface
{
    // This is the implementation of the interface method
    // Note it's final so it can't be overridden
    public final Object onCreate()
    {
        // Hence any logic right here always gets run
        // INSERT LOGIC

        return doOnCreate();

        // If you wanted you could instead create a reference to the
        // object returned from the subclass, and then do some
        // post-processing logic here
    }

    protected abstract Object doOnCreate();
}

public class Concrete extends SuperClass
{
    @Override
    protected Object doOnCreate()
    {
        // Here's where the concrete class gets to actually do
        // its onCreate() logic, but it can't stop the parent
        // class' bit from running first

        return "Hi";
    }
}

이것은 Eclipse가 구현에 슈퍼 클래스 호출을 자동으로 삽입하도록 프롬프트하는 것에 대한 질문에 실제로 대답하지 않습니다. 그러나 이것은 항상 삭제할 수 있기 때문에 어쨌든 갈 길이라고 생각하지 않습니다.

You can't actually enforce that a method must call the superclass' version with a Java keyword, or anything like that. I suspect that your exceptions simply came from some code in the parent class checking expected invariants, or something, that were invalidated by your approach. Note that this is subtly different from throwing an exception because you failed to call super.onCreate().


If you want to make absolutely sure that the superclass-method is called as well, you must trick a bit: Don't allow the superclass-method to be overwritten, but have it call an overridable protected method.

class Super
{
   public final void foo() {
      foo_stuff();
      impl_stuff();
   }

   protected void impl_stuff() {
      some_stuff_that_you_can_override();
   }
}

class Base extends Super
{
  protected void impl_stuff() { 
     my_own_idea_of_impl();
  }
}

That way, the user must call Super.foo() or Base.foo() and it will always be the base-class version as it was declared as final. The implementation-specific stuff is in impl_stuff(), which can be overriden.


To answer your actual question, the auto-creation of the call to super.onCreate() is a feature of the ADT plugin. In java, you cannot directly force a subclass to call the super implementation of a method, afaik (see the pattern described in other answers for work-around). However, keep in mind that in Android, you are not instantiating Activity objects (or Service objects) directly - you pass an Intent to the system and the system instantiates the object and calls onCreate() upon it (along with other lifecycle methods). So the system has a direct object reference to the Activity instance and is able to check (presumably) some Boolean that is set to true in the superclass implementation of onCreate(). Although I don't know exactly how it is implemented, it probably looks something like this:

class Activity
{
  onCreate()
  {
    superCalled = true;
    ...
  }
  ...
}

And in the "system" level class that receives the Intent and instantiates the Activity object from it:

...
SomeActivitySubclass someActivitySubclassObject = new SomeActivitySubclass();
someActivitySubclassObject.onCreate();
if (!someActivityObject.isSuperCalled())
{
  Exception e = new Exception(...) //create an exception with appropriate details
  throw e;
}

My guess is it's probably slightly more complex than that, but you get the idea. Eclipse automatically creates the call because the ADT plugin tells it to, as a convenience. Happy coding!


There is nothing in Java that forces calling of super, and there are plenty of examples when you wouldn't want to. The only place where you can force calling of super is in constructors. All constructors have to call a superclass constructor. One (the no arguments constructor) will be inserted if you don't write one explicitly, and if there is no no-arguments constructor then you must call it explicitly.


Eclipse is just being helpful, reminding you that you can call the superclass implementation if you want.

you are probably getting an error because you are not doing something necessary that the superclass does, since you are not calling its implementation.


Eclipse just helps you doing things right and avoid exceptions.

From http://developer.android.com/reference/android/app/Activity.html#onCreate(android.os.Bundle)

Derived classes must call through to the super class's implementation of this method. If they do not, an exception will be thrown.

참고URL : https://stackoverflow.com/questions/4217013/how-to-force-derived-class-to-call-super-method-like-android-does

반응형