본문 바로가기

LECTURE/# java basic

[초급 JAVA]자바 상속(extends) 예제로 이해하기/ super & super() 이해하기

반응형


자바 상속(extends) 예제로 이해하기/ super & super() 이해하기

By Commin December 12, 2016

안녕하세요 commin 입니다. 이번 포스팅에서는 자바의 상속(extends)을 예제를 통하여 설명하겠습니다. 상속은 어려운개념에 속하지만 꼭 알아야만 하는 개념 중 하나이니 이번에 제대로 알아보도록 합시다.

상속의 사전적 의미

- 상속이란 사람의 사망에 의한 재산 및 신분상의 지위의 포괄적인 승계를 말한다. 라고 위키백과에 명시되어 있습니다. 그렇다면 자바에서의 상속의 의미는 백과 사전에 명시되어있는 뜻과 많이 다를 까요? 아닙니다. 비슷하다고 볼 수 있습니다. 현실에서 부모에게서 물려받은 물적재산 또는 지적재산등을 자식이 상속받는 순간부터 자식의 것이 되듯 , 자바에서도 부모클래스(parent class)로부터 상속받은 자식클래스(children class)는 부모클래스의 모든 자원과 메서드 등을 자신의 것 처럼 사용 할 수 있습니다.

자바(JAVA)의 상속(extends)

  • 부모 클래스(parent class) 자식 클래스(children class)자바 지정예약어 extends에 의하여 정해집니다.
  • 하나의 부모 클래스(parent class)여러개의 자식 클래스(children)을 가질 수 있습니다.
  • 반대로 하나의 클래스는 여러개의 클래스로부터 상속을 받을수는 없습니다.
  • 부모 클래스(parent class)로부터 상속받은 자식 클래스는 부모 클래스의 자원(source) 모두를 사용 할 수 있습니다.
  • 반대로 부모클래스자식클래스의 자원을 가져다 쓸 수는 없습니다.
  • 자식클래스는 또다른 클래스의 부모 클래스가 될 수 있습니다. 
  • 자식클래스부모클래스로부터 물려받은 자원을 override 하여 수정해서 사용 할 수 있습니다.
  • 부모클래스가 상속받은 자원도 자식클래스 사용 가능합니다.

자바(JAVA)의 상속(extends) 예제로 보기


예제프로그램은 학생이 자신의 이름을 입력하면 자신의 반과 담임선생님, 그리고 반의 친구들이름까지 모두 Console창에 출력이 되게하는 프로그램입니다.

이 프로그램에 사용되는 Class는 총 세개로 School, Teacher, Student 입니다. 

School

  • 학교를 의미하는 클래스입니다.
  • 학교이름과 학교의 등급 그리고 학생들의 이름과 선생님들의 이름을 멤버필드 자원으로 가지고있습니다.
  • 학생의 이름으로 학생이 속한 반을 return 하는 기능을 가진 메서드를 가지고있습니다.
  • 학생의 이름으로 학생을 담당하는 선생님의 이름을 return 하는 기능을 가진 메서드를 가지고있습니다.

Teacher

  • 선생님을 의미하는 클래스입니다.
  • School 클래스를 상속받는 자식 클래스입니다.
  • 동시에 Student 클래스에 상속하는 부모 클래스입니다.

Student

  • 학생을 의미하는 클래스입니다.
  • Teacher클래스를 상속받는 자식 클래스입니다.
  • 메인메서드가 이곳에 존재하므로 프로그램의 시작은 Student 클래스입니다.
  • 학생의 이름을 입력받아 Console화면에 결과물을 출력합니다.

School -> Teacher -> Student 순으로 상속을 주고 받습니다.

Teacher클래스는 School에게 상속받고 Student클래스는 Teacher클래스에게 상속받으므로 Student 클래스는 School 클래스의 자원 역시 사용 할 수 있는 자식클래스입니다. 그러면 이계층구조를 그림을 그리면 아래 두개의 그림중 어떤게 맞을까요?

1번

2번

정답은 1번 그림입니다. 얼핏생각하면 최상위에 존재하는 School 클래스가 하위 클래스인 Teacher와 Student를 포함하는 형태의 2번 그림이 맞다고 생각 할 수 있지만, 자바에서 상속이 중요한 이유가 자원의 재사용성을 높이고 자원을 변형하거나 추가하는 역할을 하기 때문이기에 최하위에 존재할 것같은 Student 클래스는 부모로부터 상속받은 자원도 가지고 있고 자기자신만의 자원도 가지고있어서 1번그림처럼 부모클래스를 포함하는 형태로 그려집니다.

이제 부터 위 그림을 계속 머리속에서 생각하면서 예제 소스를 분석해 봅시다.

1
2
3
4
public class Student extends Teacher
public class Teacher extends School
public class School
 
cs

각 클래스의 선언부를 보면 클래스명 옆에 extends 부모클래스명 을 썼습니다. 이것이 바로 extends옆에 쓴 클래스를 부모클래스로 선언하는 형식입니다. Student <- Teacher <- School 순으로 상속을 하는 것이 보이죠?

1
2
3
4
5
private String name;
    public Student() {
        super();
        start();
    }
cs

Student 클래스를 먼저 보자면 처음 메인메서드로부터 호출된 생성자에서 저번시간에 잠깐 언급되었던 super라는 녀석이 보입니다. super(); 는 무엇일까요? 

super()

- 저번 포스팅에서 this()를 기억하시나요? this() 가 자기자신의 생성자를 호출하는 녀석이라고 말씀드렸는데요~ super() 는 자신의 부모클래스의 생성자를 호출하는 녀석입니다. 바로 윗단계의 부모클래스 뿐아니라 부모의 부모 또 그 부모의 부모 클래스의 생성자를 모두 호출합니다.

1
2
3
 public Teacher(){
     System.out.println("반 확인 프로그램");
 }
cs

super()로 인해서 Student의 부모클래스의 생성자인 Teacher클래스의 생성자가 호출됩니다. 그렇지만 super는 조상의 조상클래스까지 확인하는 녀석이라 일단 Teacher클래스가 상속받는 클래스가 있는지 확인합니다. School 클래스를 상속받고있죠? School 클래스로 갑니다.

1
2
3
public School() {
    System.out.println(school_name + " " + school_class);
}
cs
Shcool 클래스의 생성자가 호출되었습니다. 마찬가지로 School 클래스가 상속받는 클래스가 있는지 확인합니다. 없죠? 없으므로 School 클래스의 생성자부터 실행하고 다시 Teacher 클래스의 생성자를 실행하고 Student클래스로 돌아옵니다. 나중에 Console에 출력되는 결과를 확인해보세요^^

다시 본론으로 돌아와 Student 클래스의 start() 메서드를 살펴 봅시다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    private void start(){
        BufferedReader in =new BufferedReader(new InputStreamReader(System.in));
        System.out.print("당신의 이름을 쓰세요 >> ");
        try{
        name = in.readLine();
        if(super.getBan(name) ==null){
            System.out.println("당신은 우리학교 학생이 아닙니다.");
            return ;
        }
        System.out.println("당신의 담임 : " +super.getTeacherName(name));
        
        System.out.println("당신의 반 : " +super.getBan(name));
        
        String[] friends = super.getFriends(name);
        System.out.print("반 친구들 : { ");
        for(int i = 0 ;i<friends.length;i++){
            System.out.print(friends[i]+" ");
        }
        System.out.println("} ");
        
        
        }catch(IOException e){
            System.err.println("err!!");
        }
    }
cs

이름을 입력 받고 그 이름으로 super.getTeacherName(name);이라던지 super.getBan(name), super.getFriends(name) 메서드를 호출합니다. 여기서 Student의 전체 소스를 열어서 확인해 보세요. getTeacherName , getBan, getFriends라는 메서드가 존재 하나요? 네 그렇습니다. 이것이 상속의 힘입니다. 저 메서드들은 모두 School 클래스에 정의되어있는 메서드들입니다. 네? Student클래스는 Teacher 클래스를 상속했는데 School클래스에있는 메서드를 어떻게 사용 하느냐고요? 제가 위에서 말했다시피 부모클래스가 상속받은 클래스의 자원도 다 자식꺼입니다. 그러므로 School 클래스에 정의되어있는 메서드모두를 사용 할 수 있습니다.(당연히 private로 선언된 자원들은 쓸 수 없습니다.)

그럼 여기서 super 라는 놈은 무엇일까요?

super

- this 가 자기자신의 멤버필드를 사용할때 객체를 생성하지않고 접근할 수 있는 지정예약어라는거 기억하시나요? super는 자신의 부모의 멤버필드에 접근하는 지정예약어입니다. this와마찬가지로 생략하여 사용 할 수있습니다. 소스에서 super를 지워도 오류가 나지않는걸 확인해 보세요. 부모클래스에서 선언된 멤버필드를 마치 자신의 것 마냥 사용 할 수 있습니다. 

다시 본론으로 돌아와 override 라는 개념을 이해해 봅시다. override 는 한글로 '보수'이라는 의미입니다. 보수 공사 하다 할때 그 보수요 ! 부모에게서 물려받은 자원을 그대로 사용해도 되지만, 조금 변형시켜 사용하고자 할 때 자원을 override 하여 사용합니다. 저희 예제에서도 쓰였습니다. Student에서 쓰인 메서드들은 모두 School 클래스에서 정의도었고 모두 그대로 쓰였습니다만 한가지 getBan(name)메서드는 override되었습니다. Teacher 클래스를 봅시다.
1
2
3
4
5
@Override
public String getBan(String name){
    return super.getBan(name)+"반";
}
    
cs

Teacher클래스에서 School 클래스에있는 getBan클래스가 @Override 문구밑에 그대로 쓰여있습니다. 다만 조금 이상한게 return super.getBan(name)+"반" 을 리턴하네요. 이뜻은 무엇일까요? super.getBan()은 그대로 School에있는 getBan 메서드를 의미합니다. getBan메서드에서 String 값을 리턴받아오는것은 아시겠죠? 그 리턴받아오는 String 값에 String Value "반"을 더해서 다시 리턴하도록 Override 한것입니다. 되게 간단한 소스이지만 되게 유용합니다. 만약 끝에 "반"이라는 글씨가 없으면 좋겠다할때는 Teacher클래스를 상속받지말고 School클래스를 바로 상속받아 사용하면됩니다. 반대로 끝에 반이라는 글씨를 붙였으면 할때는 Teacher클래스를 상속받으면 되겠죠? 
아 만약 왜 다른 메서드들은 School 클래스에있는 걸 쓰는데 getBan이라는 메서드만 Teacher에있는 메서드를 사용하는지 궁금하다면 이렇게 생각하세요. 바로 윗단계의 부모에게 메서드가없으면 부모의부모 클래스를 찾고 있다면 부모클래스의 메서드를 참조한다고요 ~ 

프로그램 결과는 밑에 그림과 같습니다.

이제 모든 설명을 드린거 같습니다. 다른 포스팅에서 설명했던 부분은 설명드리지않고 넘어갔으니 모르시는부분은 댓글로 물어보거나 이전 블로그내용을 참조하세요 ^^




반응형