자바에서 구현되어있는 라이브러리를 보면 extends 라는 글자와 함께 클래스가 마치 기차처럼 줄줄이 연결되어있는 모습을 볼 수 있다. 이것은 상속을 할 때 쓰는 명령어이다! 그렇다면 상속은 뭐고, 왜 상속을 하는걸까 ?
✅ 상속 ? 왜 하는 건데 ?
우선 상속이란, 객체지향 프로그래밍에서 부모 클래스의 멤버 (필드, 메소드) 를 자식 클래스에게 물려주는 것을 의미한다. 여기서 부모클래스를 슈퍼클래스, 자식클래스를 서브클래스라고 부르기도 한다.
상속을 하는 이유는 코드를 재사용 하기 위해서이다. 잘 개발된 클래스를 상속하여, 이미 구현되어있는 기능을 가져와 쓸 수 있어 효율적으로 개발시간을 단축시킬 수도 있다.
상속은 아래 코드처럼 extends 를 사용해주면 된다.
// 부모 클래스
public class Animal {
...
}
// 자식 클래스
public class Dog extends Animal {
...
}
✅ 상속의 특징
상속은 다음과 같은 특징을 가진다.
1. 여러개의 부모클래스 상속 불가
말 그대로 여러 개의 부모클래스를 상속할 수 없다. 지원하지 않는 이유는 바로 다이아몬드 문제 때문인데, 다이아몬드 문제란 아래와 같은 상황일 때를 의미한다.
child가 father과 mother 클래스를 모두 상속한다고 가정하자. 이때 이 두 클래스에 같은 메소드가 있다면 ? 어떤 메소드를 사용해야할지 혼돈이 올 것이다. 이러한 이유로 다중상속을 지원하지 않는다.
2. 부모클래스에서 private 접근 제한을 갖는 필드와 메소드는 상속 불가
private 접근제한은 해당 클래스에서만 접근할 수 있게 하는 것이다. 따라서 자식 클래스에서는 접근할 수 없게 된다.
✅ 자식객체 생성
// 부모 클래스
public class Animal {
...
}
// 자식 클래스
public class Dog extends Animal {
...
}
이렇게 상속관계를 맺고
Dog dog = new Dog();
위와 같은 코드를 작성했다고 하자. 겉보기엔 자식클래스만 생성한 것처럼 보이지만, 부모객체가 먼저 생성된다! 나는 부모 생성자를 쓴적이 없는데..? 어째서일까 ?
우리가 자식 생성자를 만들지 않으면 아래와 같이 기본생성자가 만들어진다.
public Dog() {
super();
}
저 super() 에 의해 부모 생성자가 불려서 생성되는 것이다.
super()는 부모의 기본 생성자를 호출하는 명령어이다. 만약 직접 자식 생성자를 선언할 것이라면,
// 부모 클래스
public class Animal {
private String name;
private String kinds;
public Animal() {
}
public Animal(String name, String kinds) {
this.name = name;
this.kinds = kinds;
}
}
// 자식 클래스
public class Dog extends Animal {
private int weight;
public Dog() {
// super() 생략 시 자동으로 생성한다.
}
public Dog(String name, String kinds, int weight) {
super(name, kinds);
this.weight = weight;
}
}
이런식으로 super() 안에 매개변수를 넣어준다. 이때 매개변수의 타입과 일치하는 부모 생성자가 없으면 에러가 발생한다.
추가로 super()은 메소드 내부에서 제일 위에 넣어주어야 한다. 안그러면 에러뜸
✅ 메소드 재정의
엥 나는 부모 클래스의 메소드를 그대로 가져오기 싫은디 ? 라면 재정의해주면 된다. 이때 Override라는 애노테이션을 달아준다. 물론 생략해도 상관은 없다.
오버라이딩
오버라이딩은 부모클래스의 메소드를 자식 클래스에서 다시 재정의해 사용하는 것을 의미한다. 이때 두가지를 유의하자.
- 부모의 메소드와 선언부가 동일해야한다. (리턴타입, 메소드명, 매개변수목록 동일)
- 부모의 메소드가 private 접근제한을 가지면 오버라이딩 할 수 없다.
- 부모 메소드보다 접근 제한을 더 강하게 정의할 수 없다.
// 부모 클래스
public class Animal {
private String name;
private String kinds;
public Animal() {
}
public Animal(String name, String kinds) {
this.name = name;
this.kinds = kinds;
}
public String bark() {
return "짖는다.";
}
}
// 자식 클래스
public class Dog extends Animal {
private int weight;
public Dog() {
}
public Dog(String name, String kinds, int weight) {
super(name, kinds);
this.weight = weight;
}
@Override
public String bark() {
return "멍멍";
}
}
자식 객체에서 오버라이딩 된 메소드를 호출하면, 오버라이딩 된 자식 메소드가 호출된다. 즉, 부모 객체의 메소드가 오버라이딩 된 메소드에 의해 가려지는 것이다. (삭제되는 게 아니다)
'언어 > 자바' 카테고리의 다른 글
[JAVA] 예외처리 (Exception) _ CheckedException, UnCheckedException (0) | 2024.06.14 |
---|---|
[JAVA] 추상 클래스와 추상 메소드, 인터페이스와의 차이까지 (0) | 2024.06.14 |
[JAVA] 접근제한자, static과 final (0) | 2024.06.12 |
[JAVA] 객체와 클래스 (0) | 2024.06.11 |
[JAVA] JAVA에 대하여 (JVM, javac) (0) | 2024.06.11 |