Thinking in Java 구조 기 호출 순서

4073 단어 자바inThinking
//: polymorphism/Sandwich.java
// Order of constructor calls.
package polymorphism;
import static net.mindview.util.Print.*;

class Meal {
  Meal() { print("Meal()"); }
}

class Bread {
  Bread() { print("Bread()"); }
}

class Cheese {
  Cheese() { print("Cheese()"); }
}

class Lettuce {
  Lettuce() { print("Lettuce()"); }
}

class Lunch extends Meal {
  Lunch() { print("Lunch()"); }
}

class PortableLunch extends Lunch {
  PortableLunch() { print("PortableLunch()");}
}

public class Sandwich extends PortableLunch {
  private Bread b = new Bread();
  private Cheese c = new Cheese();
  private Lettuce l = new Lettuce();
  public Sandwich() { print("Sandwich()"); }
  public static void main(String[] args) {
    new Sandwich();
  }
} /* Output:
Meal()
Lunch()
PortableLunch()
Bread()
Cheese()
Lettuce()
Sandwich()
*///:~

이 예 에서 다른 종류 로 복잡 한 종 류 를 만 들 었 고 모든 종 류 는 자신 을 설명 하 는 구조 기 를 가지 고 있다.그 중에서 가장 중요 한 유형 은 Sandwich 로 3 층 상속(Object 의 은밀 한 상속 도 포함 하면 4 층)과 3 명의 멤버 대상 을 반영 한다.main()에 Sandwich 대상 을 만 들 면 출력 결 과 를 볼 수 있 습 니 다.이것 또한 이 복잡 한 대상 호출 구조 기 는 아래 의 순 서 를 따라 야 한 다 는 것 을 나타 낸다.
1)기본 구조 기 를 호출 합 니 다.이 절 차 는 끊임없이 반복 적 으로 돌아 갈 것 이다.먼저 이런 차원 구조의 뿌리 를 구성 한 다음 에 다음 층 의 도 출 류 등 을 통 해 최저 층 의 도 출 류 를 알 수 있다.
2)성명 순서에 따라 구성원 의 초기 화 방법 을 호출 합 니 다.
3)내 보 내기 구조 기의 주 체 를 호출 합 니 다.
구조 기의 호출 순 서 는 매우 중요 하 다.계승 을 진행 할 때,우 리 는 이미 기본 클래스 의 모든 것 을 알 고 있 으 며,기본 클래스 를 방문 하여 Public 와 proctected 의 구성원 으로 성명 할 수 있 습 니 다.내 보 내기 클래스 에서 기본 클래스 의 모든 구성원 이 유효 하 다 고 가정 해 야 한 다 는 뜻 이다.하나의 표준 방법 은 구조 동작 이 발생 하면 대상 의 모든 부분의 구성원 이 구 축 될 수 있다 는 것 이다.그러나 구조 기 내부 에 서 는 사용 할 구성원 이 모두 구축 되 었 는 지 확인 해 야 한다.이 를 확보 하기 위해 서 는 기 존 구조 기 를 먼저 호출 하 는 것 이 유일한 방법 이다.그러면 내 보 내기 구조 기 에 들 어 갈 때 기본 클래스 에서 우리 가 방문 할 수 있 는 구성원 들 은 모두 초기 화 됩 니 다.또한 구조 기 에 있 는 모든 구성원 이 효과 가 있다 는 것 을 아 는 것 도 구성원 대상 이 클래스 내 에서 정 의 를 내 릴 때(예 를 들 어 상례 의 b,c,l)가능 하 다 면 초기 화 해 야 하기 때문이다(즉,조합 방법 을 통 해 대상 을 클래스 내 에 두 어야 한 다 는 것 이다).이 규칙 을 따 르 면 모든 기본 구성원 과 현재 대상 의 대상 이 초기 화 될 수 있 습 니 다.안 타 깝 게 도 이런 방법 은 모든 상황 에 적용 되 지 않 는 다 는 점 은 다음 절 에서 볼 수 있다.
----------------------------------------------------------------------------
4
//: polymorphism/PolyConstructors.java
// Constructors and polymorphism
// don't produce what you might expect.
import static net.mindview.util.Print.*;

class Glyph {
  void draw() { print("Glyph.draw()"); }
  Glyph() {
    print("Glyph() before draw()");
    draw();
    print("Glyph() after draw()");
  }
}	

class RoundGlyph extends Glyph {
  private int radius = 1;
  RoundGlyph(int r) {
    radius = r;
    print("RoundGlyph.RoundGlyph(), radius = " + radius);
  }
  void draw() {
    print("RoundGlyph.draw(), radius = " + radius);
  }
}	

public class PolyConstructors {
  public static void main(String[] args) {
    new RoundGlyph(5);
  }
} /* Output:
Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5
*///:~
Glyph.draw()방법 은 덮어 쓰 도록 설계 되 었 으 며,이러한 덮어 쓰 기 는 RoundGlyph 에서 발생 합 니 다.그러나 Glyph 구조 기 는 이 방법 을 호출 하여 RoundGlyph.draw()를 호출 하 게 되 었 습 니 다.이것 은 우리 의 목적 인 것 같 습 니 다.그러나 출력 결 과 를 보면 Glyph 의 구조 기 가 draw()방법 을 호출 할 때 radius 는 기본 초기 값 1 이 아니 라 0 이라는 것 을 알 수 있 습 니 다.이 로 인해 화면 에 점 만 그 렸 거나 아무것도 없 을 수 있 습 니 다.우 리 는 눈 을 부 릅 뜨 고 프로그램 이 작 동 하지 않 는 원인 을 찾 으 려 고 할 수 밖 에 없 었 다.
앞의 절 에서 말 한 초기 화 순 서 는 완전 하지 않 은 데 이것 이 바로 이 수수 께 끼 를 해결 하 는 관건 이다.초기 화 된 실제 과정 은:
1)다른 모든 사물 이 발생 하기 전에 대상 에 게 분 배 된 저장 공간 을 바 이 너 리 0 으로 초기 화 합 니 다.
2)앞에서 말 한 바 와 같이 기본 구조 기 를 호출 한다.이 때 덮어 쓴 draw()방법 을 호출 합 니 다.(RoundGlyph 구조 기 를 호출 하기 전에 호출 해 야 합 니 다)절차 1 때문에 radius 의 값 이 0 인 것 을 발견 할 수 있 습 니 다.
3)성명 순서에 따라 구성원 의 초기 화 방법 을 호출 합 니 다.
4)내 보 내기 클래스 의 구조 체 를 호출 합 니 다.
이렇게 하면 모든 것 이 쓰레기 로 만 남 겨 두 는 것 이 아니 라 0 으로 초기 화 되 는 것 이 장점 이다.그 중에서'조합'을 통 해 내부 에 포 함 된 대상 인용 을 포함 하고 그 값 은 null 입 니 다.따라서 이 인용 을 초기 화 하 는 것 을 잊 으 면 실행 중 이상 이 발생 합 니 다.출력 결 과 를 볼 때 다른 모든 물건 의 값 이 0 이라는 것 을 발견 할 수 있 습 니 다.이것 은 보통 문 제 를 발견 한 증거 입 니 다.

좋은 웹페이지 즐겨찾기