프로그래밍/Java

자바(JAVA) 상속/ 생성자/ SUPER 예약어

abfc 2016. 10. 6.
반응형




상속

 - 부모의 유산을 물려받다.

 - 객체 지향 프로그래밍에서는 부모클래스에 정의된 멤버를 자식클래스가 물려받는다. 즉, 상속을 통해 기존에 있던 클래스(부모클래스)를 이용하여 새로운 클래스(자식클래스)를 만들 수 있습니다. 기존의 클래스를 이용하여 만들어내기 때문에 적은 양의 코드로 새로운 클래스륾 만들 수 있다는 장점이 있습니다.



자바에서 상속을 받게 해주려면, 새로운 클래스 이름 뒤에 extends와 상속받고자 하는 부모클래스 이름을 입력해주면 됩니다.


형식)

1
2
3
4
5
6
7
8
9
10
11
class A{ // A클래스 생성
    int x;
}
 
class B extends A{ // B클래스 생성 + A클래스를 상속받음
    int y;
}
 
class C extends B{ // C클래스 생성 + A클래스를 상속받은 B클래스를 생성(A+B)
    int z;
}
cs


설명)

A라는 클래스를 생성하고, 멤버변수 int x를 A클래스에 추가했습니다. 그리고 B라는 클래스를 생성하고 A클래스를 상속받았습니다. B클래스에는 int y라는 멤버변수가 선언되어 있고 A클래스를 상속받아서 A클래스의 int x를 사용할 수 있게됩니다. 또, C클래스는 B클래스를 상속받고 멤버변수 int z가 있습니다. A클래스를 상속받고 있는 B클래스를 상속받은 C클래스에서는 B클래스의 y만 사용할 수 있을까요? 아닙니다. A클래스를 상속받은 B클래스를 상속 받았기 때문에 C클래스는 A와 B를 모두 상속받은 상태이기때문에 int x, int y, int z 모두 사용할 수 있게됩니다.



예제를 보여드리기 전에 상속의 특징을 먼저 알아보겠습니다.

 - 2개 이상의 클래스를 한번에 상속받을 수 없습니다. 즉, 다중 상속이 불가능합니다.

 - 부모의 생성자는 상속이 되지 않습니다.

 - 부모 클래스가 가진 멤버변수와 메서드를 모두 상속받습니다.

 - 부모 클래스 내에서 멤버변수 또는 메서드가 private 접근 제한자를 사용하면 멤버변수는 상속을 받으나 바로 접근이 불가능하고, 메서드는 상속되지 않습니다.

 - static 메서드나 static 변수도 상속이 됩니다.

 - 동일한 이름의 변수가 부모클래스와 자식클래스에 둘 다 존재할 경우 부모클래스의 변수는 가려집니다. (아래의 super예약어 참조)



예제소스)

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
26
class ParentClass{ //부모클래스
    public void parentMethod(){
        System.out.println("부모클래스의 parentMethod()가 호출됨");
    }
}
 
class ChildClass extends ParentClass{ //자식클래스 생성 + 부모클래스(ParendClass)를 상속받음
    public void childMethod(){
        System.out.println("자식클래스의 childMethod()가 호출됨");
        System.out.println("부모클래스의 parentMethod()가 호출됨");
        parentMethod(); //부모클래스를 상속받았기때문에 부모의 메서드 사용 가능
    }
}
 
public class InheritanceTest {
 
    public static void main(String[] args) {
        
        //객체생성
        ChildClass child = new ChildClass();
        
        child.childMethod(); //자식클래스(ChildClass)의 childMethod()를 호출
    }
 
}
 
cs



실행결과)


설명)

메인메서드에서 자식클래스의 childMethod() 메서드를 호출하였습니다.

1
2
3
4
5
public void childMethod(){
    System.out.println("자식클래스의 childMethod()가 호출됨");
    System.out.println("부모클래스의 parentMethod()가 호출됨");
    parentMethod(); //부모클래스를 상속받았기때문에 부모의 메서드 사용 가능
}
cs


소스와 결과를 보시면 상속을 받은 자식클래스의 childMethod() 메서드에서 부모클래스의 parentMethod()를 사용할 수 있고, 호출이 됐다는 걸 확인할 수 있습니다.




상속과 생성자 그리고 super


위에 써있는 상속의 특징중에서 "동일한 이름의 변수가 부모클래스와 자식클래스에 둘 다 존재할 경우 부모클래스의 변수는 가려집니다." 라고 했습니다. 만약, 부모클래스의 변수를 이용하고 싶을 때는 어떻게 해야할까요?

-> super라는 예약어를 사용하면 됩니다. 이 예약어를 사용하면 상위클래스의 생성자에도 접근을 할 수 있게됩니다.


예제)

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class ParentClass{ //부모클래스
    private int age;
    
    public ParentClass(int age){//생성자
        this.age = age;
    }
    
    public void family(){
        System.out.println("부모입니다. 나이는 "+this.age+"살입니다.");
    }
}
 
class ChildClass extends ParentClass{ 
    private int age;
    
    public ChildClass(int age){ //생성자
        super(age+30);
        this.age = age;
    }
    
    public void family(){
        System.out.println("자식입니다. 나이는 "+this.age+"살입니다.");
    }
    
    public void childMethod(){
        family(); //자식클래스에 있는 family()
        super.family(); //부모클래스에 있는 family()
    }
}
 
public class InheritanceTest {
 
    public static void main(String[] args) {
        
        //객체생성
        ChildClass child = new ChildClass(20);
        
        child.childMethod(); //자식클래스(ChildClass)의 childMethod()를 호출
    }
 
}
 
cs


설명)

메인메서드의 내용을 보면 ChildClass 객체를 생성하면서 ChildClass의 생성자를 호출하여 20을 매개변수로 넘겨줍니다. 그럼 ChildClass 생성자내에서 super라는 예약어를 만나 부모클래스를 호출하고 age에 30을 더한 값을 부모클래스에 넘겨주어 부모클래스의 멤버변수인 age는 50으로 초기화가 됩니다.


그 후 자식클래스의 age에 매개변수 age의 값을 넣습니다. 메인메서드에서 넘겨주었던 매개변수 age의 값은 20이므로 자식클래스의 멤버변수 age에는 20으로 초기화됩니다. 

 *예제에 사용된 this는 자기 자신의 멤버를 가르킬때 사용됩니다. 즉, ChildClass 생성자에 있는 this.age는 ChildClass의 멤버변수 age를 의미합니다.


1
2
3
4
5
6
public ChildClass(int age){ //ChildClass 생성자
    super(age+30); //super를 사용하여 ParentClass 생성자로 age+30을 넘겨줌 
    this.age = age;
}
 
cs


그리고 빠져나와서 메인메서드로 돌아가 ChildClass객체 내의 childMethod()를 호출합니다.


childMethod() 에는 super 예약어를 사용해서 부모클래스의 family() 메서드를 호출합니다. super 예약어를 이용하는 이유는 자식클래스의 family()메서드에 의해 이름이 같은 부모의 family() 메서드가 가려졌기(덮어졌기) 때문입니다. 


1
2
3
4
public void childMethod(){
    family(); //자식클래스에 있는 family()
    super.family(); //부모클래스에 있는 family()
}
cs


결과)


**

super 예약어를 어떻게 사용하는지 정리를 해보자면,

 - 부모클래스의 멤벼 변수에 접근 : super.멤버변수

 - 부모클래스의 멤버 메서드에 접근 : super.멤버메서드(매개변수); super.family();

 - 부모클래스의 생성자 호출 : super(매개변수); super(age+30);


super 예약어 사용 시 주의사항입니다.

 - 반드시 자식클래스의 생성자 첫 라인에서 부모의 생성자를 호출해야 합니다.

 - 자식클래스의 생성자 내에서 반드시 부모의 생성자를 호출해야 합니다.

 - 명시적으로 자식의 클래스에서 부모의 생성자를 호출하지 않아도 super가 자동 삽입되어 부모클래스의 생성자를 호출합니다.


두번째 주의사항에 자식클래스의 생성자 내에서 반드시 부모의 생성자를 호출해야 한다고 했는데 호출하지 않아도 에러가 나지 않습니다. 그 이유는 부모클래스와 자식클래스에서 명시적으로 생성자를 정의하지 않았을 경우에 가상 머신에 의해서 디폴트 생성자가 알아서 추가됩니다. 부모클래스에는 내용이 텅 빈 디폴트 생성자가 추가되고, 자식클래스의 경우에는 super(); 가 자동으로 삽입되기때문에 에러가 나지는 않습니다.



참고 : 오버로딩과 오버라이딩








반응형

댓글

💲 추천 글