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


85

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

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


이것도 알고 싶습니다. 그리고 이클립스 만이 도움이되는 것은 아닙니다. super.onCreate ()에 대한 호출을 제거하면 앱에서 "did not call super.onCreate ()"라는 런타임 오류가 발생합니다. 그래서 네, 정말 슈퍼 메서드를 호출해야합니다. 하지만 어떻게?
Rodrigo Castro

@RodrigoCastro 각 메소드에 대한 javadocs를 검토 할 수 있습니다. 예를 들어 onCreate () 입니다.

답변:


10

여기에 소스가 있습니다 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()것입니다. 그래도 완전히 추측입니다.


2
나는 mCalled = true또한 가능한 예외에 사용되는 것 같습니다 . 아마도 그렇지 않을 수도 onCreate()있지만 실제로 그러한 예외가 발생하면 간단한 패턴을 사용합니다.
Peterdk 2010

194

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

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

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

안녕하세요.


네, 여기 머리에 못을 박았습니다. 감사.
SMBiggs 2015-08-09

아직 시도하지 않았지만 설명서를 읽으십시오. 이것은 내가 생각하기에 굉장 할 것입니다. 이것은 받아 들여진 대답이어야합니다.
Rizwan Sohaib

1
이것을 제외하고 다른 모든 대답은 완전히 쓰레기입니다. 받아 들여야합니다.
Le_Enot

3
@RizwanSohaib 그것은 당신이 아무것도하도록 강요하지 않을 것입니다. 강조 표시되고 전화해야 함을 알려줍니다. 더 복잡한 작업을 수행하려면 주석 프로세서가 필요하거나 로직을 직접 구현해야합니다. IDE에 따라 빌드를 방해 할 수도 있습니다.
frostymarvelous

1
완벽한 대답입니다. 고마워요
VO 꽝 호아

82

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

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가 구현에 슈퍼 클래스 호출을 자동으로 삽입하도록하는 질문에 대한 답변이 아닙니다. 그러나 이것은 항상 삭제할 수 있기 때문에 어쨌든 갈 길이라고 생각하지 않습니다.

실제로 메소드가 Java 키워드 또는 이와 유사한 것을 사용하여 수퍼 클래스 버전을 호출하도록 강제 할 수 없습니다. 귀하의 예외는 단순히 예상 불변 또는 귀하의 접근 방식에 의해 무효화 된 부모 클래스의 일부 코드에서 비롯된 것 같습니다. 호출에 실패 했기 때문에 이것은 예외를 던지는 것과 미묘하게 다릅니다 super.onCreate().


8

슈퍼 클래스 메서드도 호출되도록 확실히하려면 약간의 속임수를 써야합니다. 슈퍼 클래스 메서드를 덮어 쓰지 말고 덮어 쓸 수있는 보호 메서드를 호출하도록합니다.

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

이렇게하면 사용자는 Super.foo () 또는 Base.foo ()를 호출해야하며 final로 선언 된대로 항상 기본 클래스 버전이됩니다. 구현 관련 항목은 impl_stuff ()에 있으며 재정의 할 수 있습니다.


8

실제 질문에 답하기 위해 super.onCreate () 호출의 자동 생성은 ADT 플러그인의 기능입니다. Java에서는 하위 클래스가 메서드의 수퍼 구현 인 afaik을 호출하도록 직접 강제 할 수 없습니다 (해결 방법은 다른 답변에 설명 된 패턴 참조). 그러나 Android에서는 액티비티 객체 (또는 서비스 객체)를 직접 인스턴스화하지 않습니다. 시스템에 인 텐트를 전달하면 시스템이 객체를 인스턴스화하고 onCreate ()를 호출합니다 (다른 수명주기 메서드와 함께). 따라서 시스템에는 Activity 인스턴스에 대한 직접 객체 참조가 있으며 onCreate ()의 수퍼 클래스 구현에서 true로 설정된 일부 부울을 확인할 수 있습니다 (아마도). 구현 방법을 정확히 모르지만 아마도 다음과 같이 보일 것입니다.

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

그리고 Intent를 수신하고 그것으로부터 Activity 객체를 인스턴스화하는 "시스템"레벨 클래스에서 :

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

내 생각 엔 그것보다 약간 더 복잡 할 것 같지만 당신은 아이디어를 얻었습니다. Eclipse는 편의상 ADT 플러그인이이를 알려주기 때문에 자동으로 호출을 생성합니다. 즐거운 코딩 되세요!


4

Java에는 super를 강제로 호출하는 것이 없으며 원하지 않는 많은 예제가 있습니다. super를 강제로 호출 할 수있는 유일한 곳은 생성자입니다. 모든 생성자는 슈퍼 클래스 생성자를 호출해야합니다. 명시 적으로 작성하지 않으면 하나 (인수 없음 생성자)가 삽입되고, 인수가없는 생성자가 없으면 명시 적으로 호출해야합니다.


3

Eclipse는 도움이되며 원하는 경우 수퍼 클래스 구현을 호출 할 수 있음을 상기시켜줍니다.

구현을 호출하지 않기 때문에 수퍼 클래스가 수행하는 필요한 작업을 수행하지 않기 때문에 오류가 발생할 수 있습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.