Home [Java] 상속
Post
Cancel

[Java] 상속

상속 (Inheritance)

기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것

  • 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있다.
  • 코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 수정이 매우 용이해진다.

사용방법

extends 사용

1
2
class Parent {}
class Child extends Parent {}
  • Child 클래스에 Parent클래스의 멤버변수와 메서드가 추가된다.
  • 상속받는다는 것은 조상클래스를 확장(extends)한다는 의미로 해석할 수 있다.
  • 초기화블럭은 상속되지 않는다.
  • 접근제어자로 private, default가 사용된 멤버들은 상속되지 않는다기보다는 자손클래스로부터 접근이 제한되는 것으로 보는 것이 옳다.

용어

상속해주는 클래스상속받는 클래스
부모클래스자식클래스
상위클래스하위클래스
기반클래스확장된클래스

포함관계

한 클래스의 멤버변수로 선언하여 다른 클래스를 포함시키는 것

1
2
3
4
5
6
7
8
9
class Point {
  int x;
  int y;
}

class Circle {
  Point c = new Point();	// 원점
  int r;
}
  • 다른 클래스를 재사용하여 간결하고 손쉽게 클래스를 작성할 수 있다.
  • 단위클래스별로 코드가 작성되어 있어서 코드를 관리하기 수월하다.

포함관계/상속관계 구분

상속관계 : ~은 ~이다 (is-a)

포함관계 : ~은 ~을 가지고 있다 (has-a)

단일상속 (Single Inheritance)

  • 자바에서는 단일 상속만을 허용한다. (하나 이상의 클래스로부터 상속을 받을 수 없다.)
  • 인터페이스를 이용해서 보완된 형태의 다중상속을 구현할 수 있다.

다중상속을 허용할 경우

  • 장점
    • 복합적인 기능을 가진 클래스를 쉽게 작성할 수 있다.
  • 단점
    • 클래스의 관계가 매우 복잡해진다.
    • 서로 다른 클래스로부터 상속받은 멤버들의 이름이 같은 경우 구별할 수 있는 방법이 없다.

Object 클래스

모든 클래스의 조상

  • 모든 클래스 상속계층도의 제일 위에 위치하는 조상클래스이다.
  • 다른 클래스로부터 상속받지않는 모든 클래스들은 object클래스를 상속받게함으로써 이것을 가능하게 한다. (컴파일 시 컴파일러가 extends Object 추가)

오버라이딩 (Overriding)

상속받는 메서드이 내용을 변경하는 것

  • 메서드를 자손클래스에 맞게 변경해야하는 경우 사용한다.
  • 사전적 의미는 ‘덮어쓰다(overwrite)’ 혹은 ‘~에 우선하다’ 이다.

조건

메서드의 선언부가 조상클래스의 메서드와 완전히 일치해야 한다.

  • 이름, 매개변수, 리턴타입이 일치해야 한다.
  • 접근제어자는 조상메서드과 같거나 넓은 범위이어야 한다. (넓은 범위 순 : public, protected, defualt, private)
  • 예외는 조상메서드보다 적거나 같아야 한다. (선언된 예외의 개수보다 던질 수 있는 예외의 개수를 고려해야 한다.)

오버로딩과 오버라이딩의 차이

  • 오버로딩(Overloadindg) : 기존에 없는 새로운 메서드를 정의하는 것 (new)
  • 오버라이딩(Overriding) : 상속받은 메서드의 내용을 변경하는 것 (change)
1
2
3
4
5
6
7
8
9
10
11
12
class Parent {
  void parentMethod() {}
}

class Child extends Parent {
  void parentMethod() {}		// 오버라이딩
  void parentMethod(int i) {}	// 오버로딩
  
  void childMethod() {}
  void childMethod(int i) {}	// 오버로딩
  void childMEthod() {}			// 에러 (중복정의 되었음)
}

super, super()

super

조상클래스를 가리키는 참조변수

  • 자손클래스에서 조상클래스로부터 상속받은 멤버를 참조할 때 사용한다.

  • 상속받은 멤버와 자신의 클래스에 정의된 멤버의 이름이 같을 때 super를 사용해서 구별할 수 있다.
  • static 메서드는 인스턴스와 관련이 없기 때문에 static 메서드에서 사용할 수 없고 인스턴스 메서드에서만 사용할 수 있다. (this와 마찬가지)
1
2
3
4
5
6
7
8
9
10
11
12
class Parent {
  int x = 10;
}

class Child extends Parent {
  int x = 20;
  void method() {
    System.out.println(x);			// 20
    System.out.println(this.x);		// 20
    System.out.println(super.x);	// 10
  }
}

super()

조상클래스의 생성자

  • 조상 클래스의 생성자를 호출할 때 사용한다.

  • 자손클래스의 인스턴스 생성 시 자손의 멤버와 조상의 멤버가 하나의 인스턴스로 생성된다. 그래서 자손클래스의 인스턴스가 조상클래스의 멤버들을 사용할 수 있는 것이다.

  • 생성자의 첫 줄에서 조상클래스를 호출해야 한다.

    자손클래스의 멤버가 조상클래스의 멤버를 사용할 수도 있기 때문에 조상의 멤버들이 먼저 초기화되어 있어야 한다.

  • 조상클래스 생성자의 호출은 클래스의 상속관계를 거슬러 올라가면서 계속 반복된다. 마지막으로 모든 클래스의 최고 조상인 Object 클래스의 생성자Object() 까지 가서 끝이난다. 그래서 Object를 제외한 모든 클래스의 생성자는 첫 줄에 반드시 자신의 다른 생성자 또는 조상의 생성자를 호출해야 한다.

    • 그렇지 않으면 컴파일러는 생성자의 첫 줄에 자동적으로 super();를 추가한다.
    • 생성자가 정의되어있는 클래스에는 컴파일러가 기본 생성자를 자동적으로 추가하지 않는다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Point {
  int x = 10;
  int y = 20;
  
  Point(int x, int y) {
    this.x = x;
    this.y = y;
  }
}

class Point3D extends Point {
  int z = 30;
  
  Point3D() {
    this(100, 200, 300);	// Point3D(int x, int y, int z) 호출
  }
  
  Point3D(int x, int y, int z) {
    super(x, y);			// Point(int x, int y) 호출
    this.z = z;
  }
}

(Point 클래스 생성자가 정의되어있기 때문에 호출해야 함)

출처📎

  • 자바의 정석
This post is licensed under CC BY 4.0 by the author.