재정의 할 때 super () 메서드를 호출하지 않는 경우


113

나만의 Android 사용자 지정 클래스를 만들 때 extend기본 클래스입니다. 나는 기본 메서드를 재정의 할 때 다음, 나는 항상 전화 super()난 항상에서 할 것처럼, 방법 onCreate, onStop

처음부터 Android 팀이 항상 super모든 메서드 재정의를 호출하라고 조언했기 때문에 이것이 바로 이것이라고 생각했습니다 .

그러나 많은 책에서 나보다 경험이 많은 개발자들이 종종 전화를 생략하는 super것을 볼 수 있으며 그들이 지식 부족으로 그렇게하는 것은 정말로 의심 스럽다. 예를 들어 , and 에서 생략 된 기본 SAX 파서 클래스를 살펴보십시오 .superstartElementcharactersendElement

public class SAXParser extends DefaultHandler{
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if(qName.equalsIgnoreCase("XXY")) {
            //do something
        }
    }

    public void characters(char[] ch, int start, int length) throws SAXException {
        //do something
    }

    public void endElement(String uri, String localName, String qName) throws SAXException {
        if(qName.equalsIgnoreCase("XXY")) {
            //do something
        }else () {
            //do something
        }
    }
}

Eclipse 또는 다른 IDE를 통해 재정의 메서드를 만들려고 super하면 항상 자동화 된 프로세스의 일부로 만들어집니다.

이것은 단순한 예일뿐입니다. 책은 비슷한 코드가득 차 있습니다 .

언제 전화해야하는지, 언제 전화 super를 생략 할 수 있는지 어떻게 알 수 있습니까?

추신. 이 특정 예에 바인딩하지 마십시오. 많은 예에서 무작위로 뽑은 예일뿐입니다.

(초보자 질문처럼 들릴 수 있지만 정말 혼란 스럽습니다.)


3
endElement의 API 문서에는 "기본적으로 아무 작업도하지 않습니다. 응용 프로그램 작성자가이 메서드를 재정의 할 수 있습니다 ..."라는 말은 "아무것도 수행하지 않기 때문에 super를 안전하게 호출 할 수 있지만 그렇게 할 필요가 없으며 실제로 재정의 할 수 있습니다."라는 의미입니다. 해당 방법에 대한 문서를 읽으면 수행해야 / 할 수 있는지 /해서는 안되는지 종종 알 수 있습니다.
zapl 2011

1
작은 예 : 스플래시 화면에서 onBackPressed ()를 사용하고 super를 호출하지 않으므로 스플래시에서 벗어나지 않고 버튼이 비활성화됩니다.
Bojan Kogoj 2012

@sandalone 여기에서 질문 해 주셔서 죄송합니다. 인앱 결제로 VAT 세금을 처리하는 방법과 Google에서 자동으로 처리하는 국가, 그리고 수동으로 VAT 세금을 신고 / 납부해야하는 국가에 대한 경험이 있습니까? 참조 stackoverflow.com/questions/36506835/...
VIDAR 베스트 네스

답변:


144

super메서드 를 호출하면 메서드 의 동작을 재정의 하는 것이 아니라 확장 하는 것입니다.

에 대한 호출 super은 확장중인 클래스가 해당 메서드에 대해 정의한 모든 논리를 수행합니다. super메서드 재정의에서의 구현 을 호출하는 순간이 중요 할 수 있다는 점을 고려 하세요. 예를 들면 :

public class A { 
    public void save() { 
         // Perform save logic
    }
}

public class B extends A {
    private Object b;
    @Override
    public void save() { 
        super.save(); // Performs the save logic for A
        save(b); // Perform additional save logic
    }
}

에 대한 호출 은 및에 B.save()대한 save()논리를 이 특정 순서로 수행합니다. 당신이 호출되지 않은 경우 내부 , 호출 할 수 없습니다 것입니다. 당신이라고한다면 후 , 효과적으로 이후에 수행 될 것이다 .ABsuper.save()B.save()A.save()super.save()save(b)A.save()B.save()

의 동작 을 재정의 하려는 경우 super(즉, 구현을 완전히 무시하고 모두 직접 제공)을 호출해서는 안됩니다 super.

SAXParser제공 하는 예제 에서 해당 메서드 에 대한 구현DefaultHandler비어 있으므로 하위 클래스가 해당 메서드를 재정의하고 해당 메서드에 대한 동작을 제공 할 수 있습니다. 이 메소드에 대한 javadoc 에서 이것도 지적됩니다.

public void startElement (String uri, String localName,
    String qName, Attributes attributes) throws SAXException {
    // no op
}

그의 주석에서 지적했듯이 super()IDE에 의해 생성 된 코드 의 기본 호출에 @barsju대해서는 각 생성자에 암시 적 호출이 있습니다 super()(코드에 작성하지 않더라도). 즉, 해당 컨텍스트에서 super' s 기본 생성자. 는 IDE당신을 위해 그것을 적어 놓았지만 당신이 그것을 제거하면 호출 될 것입니다. 또한 생성자를 구현할 때 super()또는 인수가있는 변형 (예 :) 은 메서드 의 맨 처음super(x,y,z) 에만 호출 할 수 있습니다 .


14
또한 생성자 super()(슈퍼 클래스의 기본 생성자)는 지정하지 않더라도 항상 호출 된다는 점에 유의 하십시오. 수퍼 클래스에 기본 생성자가없는 경우 수퍼 클래스의 생성자 중 하나를 하위 클래스 생성자의 첫 번째 명령문으로 명시 적으로 호출하지 않으면 컴파일 오류가 발생합니다.
barsju

1
네, 기본적으로 게으름 일뿐입니다. 우리가 아는 방법의 경우 아무 것도하지 않고 간결함을 위해 생략합니다
Voo

1
귀하의 소중한 의견에 감사드립니다, @barjsu, 나는 이러한 세부 사항을 답변에 포함했습니다.
Xavi López 2012

16

언제 super에 전화해야하는지, 언제 전화를 생략 할 수 있는지 어떻게 알 수 있습니까?

일반적으로 특별한 API 방법은 기본 프레임 워크 컨텍스트 라이프 사이클에 중요한 의미가있는 경우, 항상 명시 적으로 언급되고처럼, API 문서에서 강조 Activity.onCreate()API 문서 . 또한 API가 강력한 설계를 따르는 경우 프로젝트 컴파일시 소비자 개발자에게 경고하기 위해 몇 가지 예외를 throw하고 런타임에 오류가 발생하지 않도록해야합니다.

이것이 API 문서에 명시 적으로 명시되지 않은 경우 소비자 개발자는 API 메서드를 재정의 할 때 반드시 호출해야하는 것이 아니라고 가정하는 것이 안전합니다. 기본 동작 ( super메소드 호출)을 사용할지 또는 완전히 재정의 할지 여부는 소비자 개발자에게 달려 있습니다.

조건이 허용되면 (저는 오픈 소스 소프트웨어를 좋아합니다) 소비자 개발자는 항상 API 소스 코드를 확인하고 메서드가 실제로 어떻게 작성되는지 확인할 수 있습니다. 예를 들어 Activity.onCreate()소스DefaultHandler.startElement()소스 를 확인하십시오 .


추가 설명을 해주셔서 감사합니다. 소스 코드를 확인하도록 상기시켜 주셔서 감사합니다.
sandalone

7

머릿속에서해야 할 테스트는 다음과 같습니다.

"이 방법의 모든 기능을 수행 한 다음 나중에 작업을 수행해야합니까?" 그렇다면을 호출 super()한 다음 메서드를 완료합니다. 이는 onDraw()백그라운드에서 많은 것을 처리하는와 같은 "중요한"메소드 에 해당됩니다.

(재정의 할 대부분의 메서드와 마찬가지로) 일부 기능 만 원하는 경우을 호출하고 싶지 않을 것입니다 super().


3

그럼 사비는 더 나은 대답을했다 ...하지만 당신은 아마 무엇을하는지 알 수 있습니다super() 기본 동작으로 수행 한 어떤 오버라이드 (override) 방법 ... 그것은 광고에 전화했을 때 어떻게 ..

예 :

onDraw() 

재정의되었을 때 뷰 클래스의 메소드 .. super.onDraw ()라고 말하기 전에 무언가를 그립니다. 뷰가 완전히 그려지면 나타납니다. 따라서 superAndroid에는 onCreate ()와 같은 매우 중요한 작업이 있기 때문에 여기서 호출 해야합니다.

하지만 동시에

onLongClick()

당신이 이것을 재정의 할 때 당신은 EditText 또는 다른 유사한보기에 대한 옵션 목록이있는 대화 상자를 불러 오기 때문에 super를 호출하고 싶지 않습니다. 그것은 기본적인 차이점입니다 .. 당신은 그것을 몇 번 남겨 두도록 선택할 수 있습니다. onCreate() , onStop()OS가 처리하도록해야하는 것과 같은 다른 방법 ..


2

귀하의 질문을 명확하게 이해하지 못했지만 super메서드를 호출하지 않는 이유에 대해 묻는 경우 :

super메서드 를 호출하는 이유가 있습니다 . 부모 클래스에 인수가없는 생성자가 없으면 자식 클래스를 만들 수 없으므로 부모 클래스에 인수없는 생성자를 유지해야하거나 자식 클래스 생성자의 맨 위에 super()호출 문 을 정의 argument(how much argument constructor you have used in super class)합니다.

이게 도움이 되길 바란다. 그렇지 않다면 알려주세요.


2

나는 다음과 같은 제약 배열 목록을 구현했다.

public class ConstraintArrayList<T> extends ArrayList<T> {
  ConstraintArrayList(Constraint<T> cons) {this.cons = cons;}
  @Override
  public boolean add(T element) {
    if (cons.accept(element))
      return super.add(element);
    return false;
  }
}

코드를 살펴보면 실제로 수퍼 클래스가 목록에 요소를 실제로 추가하도록하기 전에 몇 가지 사전 검사를 수행합니다. 이것은 메서드 재정의에 대한 두 가지 이유 중 하나를 알려줍니다.

  1. 수퍼 클래스가 수행 할 수있는 작업을 확장하려는 확장 성
  2. 새가 움직이는 (날다) 및 개구리가 움직이는 (홉) 방식이 각 하위 클래스에 고유 한 이동 의미론의 일반적인 동물 왕국 예제에서와 같이 다형성을 통해 특정 동작을 추가하려는 특이성.

2

Android 프레임 워크에서 어떤 재정의 된 메서드 super가이 질문을 호출해야하는지 궁금한 사람들을 위해 여기에 2019 년의 현재 힌트 가 있습니다 . Android Studio 3+가 필요할 때 알려줍니다 .

여기에 이미지 설명 입력

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