티스토리 뷰
728x90
반응형
상속이란?
- 자바에서 상속이란 부모 클래스에 정의된 필드와 메서드를 자식 클래스가 물려 받는것입니다.
상속의 장점
- 클래스의 간결화 - 멤버 변수의 중복 작성 불필요
- 클래스 관리 용이 - 클래스들을 계층적으로 분류
- 클래스의 재사용성과 다형성
상속의 특징
- 상속되는 클래스의 멤버 변수나 메서드를 선택적으로 상속받을 수 없습니다.
- 상속을 받게 되면 super 클래스의 모든 속성과 기능을 상속받아 사용할 수 있습니다.
- 생성자는 상속되지 않습니다.
- 하나의 부모 클래스는 여러개의 자식 클래스를 가질 수 있습니다.
- 자바의 최상위 클래스는 Object 클래스이며, 모든 클래스는 Object 클래스의 자식입니다.
super 키워드
- 자바에서 자식 객체를 생성하면 부모 객체의 멤버 변수나 메소드를 사용할 수 있습니다. 그렇다면 자식 객체 생성 시 부모객체 생성이 되는가?
- 위의 답은 그렇지 않습니다. 자식 객체 생성시 부모 객체가 먼저 생성된 뒤에 자식 객체가 생성됩니다.
`
public class Car {
public Car() {
System.out.println("부모 생성자 호출 : Car");
}
}
public class SuperCar extends Car{
public SuperCar() {
System.out.println("자식 생성자 호출 : SuperCar");
}
}
public class Example {
public static void main(String[] args) {
// 자식 생성자 객체 생성
SuperCar superCar = new SuperCar();
}
}
// 아웃풋
//부모 생성자 호출 : Car
//자식 생성자 호출 : SuperCar
- super 키워드는 상속관계에서 부모 클래스의 멤버 변수나 메서드를 참조하기 위해서 사용됩니다.
- 자식 클래스에서 부모 클래스의 멤버 변수나 메서드를 오버라이딩한 경우 오버라이딩된 자식 메서드가 아닌 부모 클래스의 메서드를 사용하기 위해 사용됩니다.
- 객체를 생성하기 위해서는 생성자가 필요합니다. 위의 예제에서는 부모객체를 따로 생성을 하지 않았는데 어떻게 생성이 된걸까요?
- 이는 개발자가 따로 부모 객체의 생성자를 자식 클래스에 지정해 놓지 않는다면 컴파일러가 super() 메서드를 통해 부모의 기본 생성자를 호출합니다.
-
super()
- 자식 클래스에서 부모 객체의 생성자를 호출하고 싶은 경우에도 위와 같은 방법으로 작성을 하면 됩니다.
자식 클래스에서 부모 클래스의 생성자를 선택하는 방법
Case 01 - 부모 클래스의 기본 생성자가 자동으로 선택되는 경우
- 개발자가 명시적으로 부모 클래스의 생성자를 선택하지 않는 경우 컴파일러는 기본 생성자이든 매개변수를 가진 생성자이든 부모 클래스에서 기본 생성자가 선택됩니다.
- SuperCar 클래스는 Car 클래스를 상속받고 있습니다. Car 클래스에는 2개의 생성자가 있지만 SuperCar의 기본 생성자가 호출되면 부모 클래스(Car)의 기본 생성자가 호출됩니다.
public class Car {
private String name;
public Car() {
System.out.println("기본 부모 생성자 호출 : Car");
}
public Car(String name) {
System.out.println("매개변수를 가진 부모 생성자 호출 값 : " + name);
}
}
public class SuperCar extends Car{
public SuperCar() {
// 컴파일러가 super(); 코드를 생성하며 부모 클래스의 기본 생성자 호출
System.out.println("기본 자식 생성자 호출 : SuperCar");
}
}
public class Example {
public static void main(String[] args) {
// 자식 생성자 객체 생성
SuperCar superCar = new SuperCar();
}
}
// 아웃풋
// 기본 부모 생성자 호출 : Car
// 기본 자식 생성자 호출 : SuperCar
Case 02 - super()를 사용하여 명시적으로 부모 클래스의 생성자 선택
- 자식 클래스의 생성자에서 super() 키워드를 사용하면, 부모 클래스의 생성자를 명시적으로 선택할 수 있습니다. super()는 부모 클래스의 생성자를 호출하는 코드입니다.
- super()는 반드시 생성자의 첫 라인에 작성되어야 합니다.
public class Car {
private String name;
public Car() {
System.out.println("기본 부모 생성자 호출 : Car");
}
public Car(String name) {
System.out.println("매개변수를 가진 부모 생성자 호출 값 : " + name);
}
}
public class SuperCar extends Car{
public SuperCar() {
// 기본 생성자 호출시 부모 클래스의 기본 생성자 호출
System.out.println("기본 자식 생성자 호출 : SuperCar");
}
public SuperCar(String name) {
// 매개변수 있는 생성자 호출시 부모 클래스에 메개변수가 일치하는 생성자 호출
super("현대차");
System.out.println("매개변수를 가진 자식 생성자 호출 : SuperCar");
}
}
public class Example {
public static void main(String[] args) {
// 자식 생성자 객체 생성
SuperCar superCar = new SuperCar("슈퍼카");
}
}
// 아웃풋
// 매개변수를 가진 부모 생성자 호출 값 : 현대차
// 매개변수를 가진 자식 생성자 호출 : SuperCar
super.멤버 변수
- 자식 클래스의 멤버변수와 부모 클래스의 멤버변수간 이름이 동일한 경우 부모 클래스의 멤버변수에 접근하는 경우 사용됩니다.
super.메서드
- 자식 클래스의 메서드와 부모 클래스의 메서드간 이름이 동일한 경우 부모 클래스의 메서드에 접근하는 경우 사용됩니다.
상속시 주의 사항
- 부모 클래스에 기본 생성자가 없고 매개변수가 있는 생성자가만 있다면 자식 클래스의 생성자 첫 라인에는 반드시 부모 클래스의 생성자를 명시적으로 호출해줘야 합니다. 그렇지 않으면 컴파일 에러가 발생하게 됩니다.
- 아래 예제는 컴파일 오류가 발생하게 됩니다.
- 문제가 발생하는 이유는 자식 클래스의 모든 생성자가 실행될 때 부모 클래스의 기본 생성자를 찾는데 부모 클래스에서는 기본 생성자가 없기 때문에 문제가 발생하고 있습니다.
- 자바에서는 매개 변수가 있는 생성자를 만든 경우 컴파일러가 기본적으로 기본 생성자는 따로 만들어 주지 않습니다.
public class Car {
private String name;
public Car(String name) {
System.out.println("매개변수를 가진 부모 생성자 호출 값 : " + name);
}
}
public class SuperCar extends Car{
private String name;
public SuperCar() {
System.out.println("기본 자식 생성자 호출 : SuperCar");
}
public SuperCar(String name) {
System.out.println("매개변수를 가진 자식 생성자 호출 : SuperCar -> " + name);
}
}
public class Example {
public static void main(String[] args) {
// 자식 생성자 객체 생성
SuperCar superCar = new SuperCar("슈퍼카");
}
}
생성자의 기본 전제
- 개발자가 명시적으로 생성자를 만들지 않으면 컴파일러가 default 생성자를 생성하게 됩니다.
- 그런데 만약 개발자가 매개변수가 있는 생성자를 만들게 되면 컴파일러는 default 생성자를 생성하지 않게 됩니다.
- Car 클래스를 상속받은 SuperCar 클래스의 생성자를 호출하게 되면 개발자가 super(); 를 명시적으로 작성하지 않아도 super(); 라는 코드가 자동으로 삽입됩니다. 즉 Car 클래스의 default 생성자를 호출하게 됩니다.
그런데 Car 클래스에서는 매개변수가 있는 생성자가 이미 선언되어 있기 때문에 default 생성자를 생성하지 않게 되는데 근데 super();는 매개 변수가 없는 기본 생성자를 호출하기 때문에 컴파일 에러가 발생하게 됩니다.
해결 방법
Case 01 - 부모 클래스의 default 생성자가 호출하지 않도록 명시적으로 작성해줍니다.
public class SuperCar extends Car{
private String name;
public SuperCar() {
super("현대차");
System.out.println("기본 자식 생성자 호출 : SuperCar");
}
public SuperCar(String name) {
super("기아차");
System.out.println("매개변수를 가진 자식 생성자 호출 : SuperCar -> " + name);
}
}
Case 02 - 부모 클래스에 default 생성자를 명시적으로 작성해줍니다.
public class Car {
private String name;
// 명시적으로 기본 생성자 생성
public Car() {
System.out.println("기본 부모 생성자 호출 : Car");
}
public Car(String name) {
System.out.println("매개변수를 가진 부모 생성자 호출 값 : " + name);
}
}
메서드 오버라이딩
- 상속은 extends 키워드를 사용하여 부모 클래스의 멤버변수나 메서드를 물려 받게됩니다. 이때 물려 받았으면 그 자체를 같은 방식으로 사용할 수 있지만 대부분 재정의하여 사용하는 경우가 많습니다. 이때 부모 클래스로부터 상속받은 메서드를 재정의하는 행위를 오버라이딩이라고 합니다.
- 재정의를 하는경우 부모의 메서드는 은닉되고 자식의 메서드가 호출됩니다.
public class Car {
public void myCarName(){
System.out.println("소나타");
}
}
public class SuperCar extends Car{
@Override
public void myCarName() {
System.out.println("벤츠");
}
}
public class Example {
public static void main(String[] args) {
SuperCar superCar = new SuperCar();
superCar.myCarName(); // 벤츠
}
}
오버라이딩 규칙
- 부모 클래스의 메서드와 동일한 리턴타입과 이름, 매개변수를 가져야합니다.
- 접근 제한자를 더 강하게 둘 수 없습니다.
- 부모 메서드는 public이지만 자식이 private일 수 없습니다.(반대는 가능)
- 새로운 예외를 throws할 수 없습니다.
728x90
반응형
'JAVA > JAVA기본' 카테고리의 다른 글
JAVA - 추상 클래스란? (2) | 2022.01.16 |
---|---|
JAVA - 다이나믹 메소드 디스패치란? (0) | 2022.01.11 |
JAVA - Class란? (feat.인스턴스, 메서드, 생성자, this) (0) | 2022.01.04 |
JAVA - Queue이란? 그리고 구현 (0) | 2022.01.01 |
JAVA - Stack이란? 그리고 구현 (0) | 2021.12.31 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- spring boot redis 대기열 구현
- spring boot 엑셀 다운로드
- spring boot poi excel download
- spring boot redisson sorted set
- 트랜잭셔널 아웃박스 패턴 스프링 부트 예제
- polling publisher spring boot
- spring boot redisson destributed lock
- spring boot excel download oom
- microkernel architecture
- java userThread와 DaemonThread
- 자바 백엔드 개발자 추천 도서
- @ControllerAdvice
- 람다 표현식
- 공간 기반 아키텍처
- pipe and filter architecture
- transactional outbox pattern
- pipeline architecture
- JDK Dynamic Proxy와 CGLIB의 차이
- spring boot excel download paging
- 트랜잭셔널 아웃박스 패턴 스프링부트
- 레이어드 아키텍처란
- transactional outbox pattern spring boot
- redis sorted set
- redis sorted set으로 대기열 구현
- space based architecture
- spring boot redisson 분산락 구현
- 서비스 기반 아키텍처
- redis 대기열 구현
- service based architecture
- java ThreadLocal
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함