2016-09-29 3 views
0

수퍼 클래스의 생성자가 서브 클래스에서 호출되고 서브 클래스가 생성자가 호출하는 수퍼 클래스의 메서드를 숨길 것이라고 가정합니다. 그런 다음 java는 수퍼 클래스의 생성자에서 하위 클래스의 메서드를 사용합니다. 그러나 대부분의 경우에 이것은 수퍼 클래스가 서브 클래스를 염두에두고 설계되지 않기 때문에 바람직한 행동이 아닙니다. 다른 방법입니다.java에서 클래스 자신의 메서드를 사용하는 생성자를 적용하는 방법

최종 클래스 나 정적 클래스를 만들지 않고 이름을 변경하거나 코드를 생성자에 복제하지 않고 어떻게 슈퍼 클래스 자체 메서드로 초기화를 수행 할 수 있습니까? (예, 왜?이 만족스럽지 못한 행동의 숨겨진 원리 어떤 경우 또는 자바는? constuctors에서 재정의 방법을 사용하여 낙담/지원하지 않는?)

내가 명시 적 캐스트를 시도 ...

((SuperClass) this).method() 

...이 작동하지 않습니다.

예 :

Exception in thread "main" java.lang.NullPointerException 
    at testingJava.SubClass.set(SubClass.java:19) 
    at testingJava.SuperClass.<init>(SuperClass.java:7) 
    at testingJava.SubClass.<init>(SubClass.java:10) 
    at testingJava.MainClass.main(MainClass.java:9) 

편집 :

3 class SuperClass { 
4  private int[] valField = new int[10]; 
5 
6  SuperClass(int[] cloneField) { 
7   for (int i = 0; i < 10; i++) set(i, cloneField[i]); 
8  } 
9 
10  void set(int pos, int val) { 
11   if (val < 0) throw new IllegalArgumentException("val must be positive; val was " + val); 
12   if (pos < 0 || pos > 10) throw new IllegalArgumentException("pos must be within [0, 10]; pos was " + pos); 
13   valField[pos] = val; 
14  } 
15 
16  int get(int pos) { 
17   return valField[pos]; 
18  } 
20 } 


6 class SubClass extends SuperClass { 
7  private Set<Integer> isZero = new HashSet(); 
8 
9  SubClass(int[] cloneField) { 
10   super(cloneField); 
11   isZero.clear(); 
12   for (int i = 0; i < 10; i++) 
13    if (this.get(i) == 0) 
14     isZero.add(i); 
15  } 
16  
17  void set(int pos, int val) { 
18   super.set(pos, val); 
19   if (val == 0) isZero.add(pos); 
20   else isZero.remove(pos); 
21  } 
22 } 

이 결과 일부 추가 테스트 및 탐사 이상한 솔루션이 밝혔다. 수퍼 클래스를 두 부분으로 나누고 생성자에서 super.method()를 사용하면 자바 인터프리터에 올바른 메서드를 정렬 할 수있는 명확한 부호를 부여하는 것처럼 보입니다.

I am the super class. 
+4

"constuctors에서 재정의 할 수있는 메소드를 사용하거나 지원하지 못하도록합니다."- [예, 방해하지 않습니다] (http://stackoverflow.com/questions/3404301/whats-wrong-with-overridable-method-calls- in-constructors) – resueman

+1

당신은 [이 질문] (http://stackoverflow.com/a/3404369/4216641)을보고 싶습니다. 짧은 대답 : 자바에서는 불가능합니다.어쩌면 반사에 의해 숨겨진 방법을 얻을 수있는 방법이 있을지도 모르지만, 이것은 성과가없고 유지하기가 어렵습니다. – Turing85

+0

정말 오버라이드 된 메소드를 호출해야하는 경우 항상 서브 클래스의 생성자에서 super.method()를 사용할 수 있습니다. –

답변

1

하나가 수행해서는 안 확장 가능한 클래스에서 재정의 메서드를 호출 :

예 :에

class SuperClass { 
    void message() { 
     System.out.println("I am the super class."); 
    } 
} 

class MiddleClass extends SuperClass { 
    MiddleClass() { 
     super.message(); 
    } 
} 

class SubClass extends MiddleClass { 
    void message() { 
     System.out.println("I am the sub class."); 
    } 
} 
이제

...

SubClass mySubClass = new SubClass(); 

... 평가 :

class A { 
    A() { 
     init(); 
    } 
    void init() { 
    } 
} 

class B extends A { 
    String s = ""; 
    String t = null; 
    String u; 

    B() { 
     // - s, t and u are zeroed (null) 
     // - super() is called 
     // - - init() assign "sss" to s, "ttt" to t and "uuu" to u 
     // - field initialisations are done for initialized fields 
     // assigns "" to s and null to t. 
     System.out.printf("s=%s, t=%s, u=%s%n", s, t, u); 
     // s=, t=null, u=uuu 
    } 

    @Override 
    void init() { 
     s = "sss"; 
     t = "ttt"; 
     u = "uuu"; 
    } 
} 

일반적으로 컨테이너 클래스는 이러한 "초기화"메소드, NullPointerException 또는 초기화되지 않은 결과 (여기서는 s)에서 "초기화"됩니다.

솔루션 : 여러 생성자가 this(...)를 호출하고 하나의 생성자의 모든 정교한 초기화를 수집하는 경우는

  • 말했다

    • 개인과 마지막 방법 만한다.

    그래서 초기화 방법이 없습니다. 또한 단위 테스트하기 어려운 복잡한 초기화가있는 생성자의 경우 코드 냄새가 날 수도 있습니다. 그런 다음 생성자는 많은 작업을 수행해서는 안되며 추가 작업은 void open(...) 또는 그와 같은 작업을 수행해야합니다. 특히 생성자가 여러 개인 경우.

  • +1

    기본 문제는 자바에서 메소드 바인딩이 항상 실제 객체를 참조하는 것으로 보입니다. java에는 상속 범위가 없습니다. – Koudela

    +0

    @Koudela 예, 친절한'새로운 슈퍼 (+ 여분의 방)'그리고 클래스를 업그레이 드하십시오. –

    관련 문제