더 쉽게 쓴 자바(소.자.바)19.11.07

[소.자.바] 4.7 super(완료)

gnosis90 2019. 12. 16. 16:54

* 본 블로그는 개인 공부용으로 해당 내용은 자북의 '최영관'님이 저자이신 소설같은 자바를 읽고 정리한 내용으로써 문제가 있을 시 모두 내리도록 하겠습니다.

 

4.7.1 super 참조변수

 

 super 참조변수란 상속구조에서 디자인 타임에 사용할 수 있는 상위 클래스의 참조 변수이다. 다시 말하자면 상위 클래스를 참조할 수 있는 유일한 키로, super 참조변수를 통해 상위클래스를 참조할 수 있는 방법이라 할 수 있다.

 

- 76 -

 

4.7.2 super를 이용하여 상위 클래스를 참조

 

 아버지의 클래스로부터 상속을 받았다면 아버지 클래스의 모든 것은 아들 클래스의 것이 된다. 아들 클래스에서는 아버지(클래스의) 것도 내 것이고, 내(클래스) 것도 내 것이니 this라는 키워드를 이용해서 아버지의 멤버에 접근할 수 있다. 물론 아버지의 public이나 protected 접근 지정자를 사용하는 멤버에만 접근할 수 있지만 말이다(이 말인 즉슨 private와 default로는 접근이 불가능하다는 말).

 

 이것은 너무나 당연한 상속의 개념으로써, 아버지 클래스와 아들 클래스의 상속 관계에서는 재정의 메소드가 존재(할 수 있다.)한다. 그리고 아들 클래스 내부에서 재정의 된 메소드를 호출하면, 무조건 아들의 재정의 된 메소드가 호출되는데, 이는 재정의 자체(에서)는 아버지의 메소드를 무시하고 있기 때문이다. 그런데 실제로는(엄밀히 말하자면), 재정의 된 메소드 하나와 아버지의 무시되어진 메소드 하나, 즉 총 2개의 메소드가 함께 존재하게 된다. 그렇다면 아들의 입장에서 아버지의 메소드를 호출 하고자 한다면 어떻게 해야할까?

 

나쁜 아들이 아닐 수 없다. 자신(=아들)이 재정의한 아버지의 메소드를 호출할 수 있게 (허용)할 만큼 아버지 클래스는 과연 너그러울까? 무시되어진 아버지 클래스(내(內))의 메소드를 호출하는 방법은 바로 super 참조변수를 이용하는 것이다. super는 this와 같은 원리로 동작된다. 그래서 super 자체는 디자인 타임에 아버지를 참조하는 유일한 참조변수이다.

 

NewSon.java                                                                //super를 테스트하기 위한 예제

  class NewFather{

    pubic void overrideFunc(){

      System.out.println("아버지의 함수");

     }

  }

 

  public class NewSon extends NewFather{

    public void overridefunc(){

      System.out.println("아들의 재정의 함수");

  }

      

  public  void testFunc(){

    super.overrideFunce();

  }

 

  public static void mian(String[] args){

    NewSon s = new NewSon();                                         //재정의 된 함수  호출.

    s.overrideFunc();                                                         //super를 이용한 아버지 호출.

    s.testFunc();

  }

}

 

C:\examples\4.Class for basic Java>javac NewSon.java

C:\examples\4.Class for basic Java>java NewSon.java

아들의 재정의 함수

아버지의 함수

 

- 77 -

     

 상속을 아들 클래스가 받았다고 한다면 아버지 무시하기 즉, 특정 메소드를 Overriding하고 있는 것이다.

당연히 아버지 클래스의 메소드는 아들 클래스와 같은 이름의 메소드가 존재하기 때문에 아들이 이 메소드를 사용한다면 무시되는데, 그렇다면 만약 무시되어진 아버지 클래스의 메소드를 사용하고 싶다면 어떻게 해야하는 걸까?

방법이 없다. ANSI C++에서(도) 이것에 대한 해결책을 제시해 주고 있지만 자바에서는 super라는 키워드를 통해서 제공한다.

 

public void testFunc(){

   super.overrideFunc();

}

 

testFunc() 메소드에서 super를 이용하여 아버지의 메소드를 호출하고 있다. 자신의 메소드와 아버지의 메소드를 구분하기 위해서 이것을 사용하는 것일 뿐 별다른 이유는 없다.

 

4.7.3. super를 이용한 생성자 메소드 호출

 

 상속을 받았을 경우 아버지 클래스의 생성자 메소드가 매개변수를 가지고 있다면 어떻게 될까?

잘 생각해보면 어쨌든 아버지 클래스의 생성자 메소드가 호출 된 후에 아들의 생성자 메소드가 호촐되는 것은 당연한 일이다. 그렇다면 아들이 상속 받았을 경우 아버지의 생성자에 매개변수는 누가 넣어 줄 수 있을까? 아버지의 생성자에 매개변수를 넣어주지 않아도 아버지의 생성자가 호출 가능할까?

 

 아버지 클래스의 생성자 메소드가 매개변수를 가지고 있다면 아들 입장에서는 아버지의 생성자 메소드에 매개변수를 넣어주어야 하는 의무가 있다. 이것은 아들이 아버지를 상속 받았기 때문이며(부양의 의무와 같이...?) 자동으로 아들이 생성되어질 때 아버지의 생성자 메소드를 호출하기 때문이다(의문점 : 그렇다면 이것은 아버지 메소드를 호출하지 않아도 통상적으로 아들 메소드가 호출되면 무조건적으로 사용하던 사용하지 않던 아버지 메소드가 호출된다는 말인가?).

 

 결론적으로 말하자면 이것은 불가능한 일이다. 무조건적으로, 절대적으로, 생성자에 매개변수가 존재한다면 생성자의 매개변수에 형과 개수를 맞추어 주어야만 호출이 가능하다. 아들 클래스가 상속을 받아버린 상태이고 그리고 아들은 아버지의 생성자에 매개변수를 넣어줄 의무가 있다. 이것을 무시한다면 아들(메소드는)은 만들어(생성되어)질 수 없다.

 

SuperSon.java                                         //this를 테스트하기 위한 예제

  class SuperFather{

    private String name;

    pubic SuperFather(String name){

      this.name = name;

      System.out.println("name : " + name);   

    }

  }

  

  public class SuperSon extends SuperFather{

    public SuperSon(String str){

      super(str); 

    }  

    public static void main(String[] args){

      SuperSon s = new SuperSion("상속의 super Test"); 

    } 

  }

 

- 78 -

 

C:\examples\4.Class for Basic Java>javac SuperSon.java

C:\examples\4.Class for Basic java>java Superson

name : 상속의 super Test

 

 

4.7.4. 결론

 

4.8. 마무리

 

 이 장에서는 자바 프로그램을 하기 위한 기본적인 객체지향의 기법들을 배워 보았다. 상속, Overloading, Overriding과 같은 개념들은 자바에서 아주 큰 부분을 차지하고 있고 이러한 개념들에 대한 이해가 없이 자바를 배운다는 것은 불가능하다. 기본적인 개념들은 아주 쉽지만 상속 관계와 연결되면서 나타나는 여러 개념들은 아직도 충분히 이해하기엔 설명이 부족하다는 말 밖에는 할 말이 없다.

 

다음 장에서는 이러한 개념들을 총동원하면서 어떻게 다형성과 연결되는지에 대해서 알아보도록 하겠다.