1. 상속의 정의
다른 클래스가 가지고 있는 멤버(필드, 메서드)들을 새로 작성할 클래스에서 직접 만들지 않고
상속을 받음으로써 새 클래스가 자신의 멤버처럼 사용할 수 있는 기능
1) 목적
클래스의 재사용, 연관된 일련의 클래스들에 대한 공통적인 규약 정의
2) 방법
클래스 간의 상속 시에는 extends 키워드 사용
[표현식]

public class Academy extends Company {}
자식 부모
3) 장점
- 코드 길이 감소
→ 부모 필드/메서드를 자식이 안써도 사용 가능
- 재사용성 증가
→ super(), super 참조변수를 이용해
자식이 부모코드를 호출해서 자식 코드 길이 감소
- 공통적인 코드 관리, 유지 보수성 증가
→ 부모의 코드만 수정해도
부모 코드를 활용하던 자식이 코드도 일괄 수정됨
- 자식에게 상속하는 기능의 이름을 강제할 수 있음
→ 오버라이딩 시 부모의 메서드명과 동일해야 한다!
| 오버라이딩( Overrriding) | 오버로딩(Overloading) |
| 하위 클래스에서 메서드 정의 | 같은 클래스에서 메서드 정의 |
| 메서드 이름 동일 매개변수 동일(개수, 타입, 순서) 리턴 타입 동일 |
메서드 이름 동일 매개변수 다름(개수, 타입, 순서) 리턴 타입 상관없음 |
| 자식 메서드의 접근 범위가 부모 메서드의 접근 범위보다 넓거나 같아야 함 |
접근 제어자와 상관 없음 |
| 자식 메서드의 예외 수가 부모 메서드의 예외 수보다 적거나 범위가 좁아야 함 |
예외처리와 상관없음 |
2. Object
- 모든 클래스(객체)의 최상위 부모
- 모든 클래스(객체)가 공통적으로 가져야 하는 기능이 모여있음
- 클래스 선언부에 아무런 상속 구문(extends)이 작성되어 있지 않으면
컴파일러가 extends Object 구문을 추가해준다!!
3. final 메서드
- 오버라이딩 불가
→ 부모의 메서드가 완벽해서 또는 재정의하면 문제가 되서
더이상 오버라이딩을 못하게 하겠다
(마지막으로 정의된 메서드)
public final 반환형 메서드명(){}
#예제
[부모 역할 클래스]
package dto;
/*Object 클래스
* - 모든 클래스(객체)의 최상위 부모
* - 모든 클래스(객체)가 공통적으로 가져야 하는 기능이 모여있음
*
* - 클래스 선언부에 아무런 상속 구문(extends)이
* 작성되어 있지 않으면
* 컴파일러가 extends Object 구문을 추가해준다!!
*
*/
/**
* 부모 역할 클래스
*/
public class Parent extends Object {
// 부모 필드
// protected 접근 제한자
// - 같은 패키지 : 객체 생성 후 사용
// ex ) 같은 패키지 클래스에서
// Parent p = new Parent(); p.lastName;
// - 상속 관계 자식 클래스 : 자식 클래스에서 직접 사용
// ex) 자식 클래스에서 lastName; 작성
protected String lastName = "홍"; // 명시적 초기화
private String address = "서울시 중구 남대문로 120";
private int money = 100_000_000; // _ : 자릿수 구분(해석 X)
private String car = "그랜져";
// 기본 생성자
public Parent() {
System.out.println("부모 - 기본 생성자로 객체 생성");
}
// 매개 변수 생성자(Alt + shift + s -> o)
public Parent(String address, int money, String car) {
this.address = address;
this.money = money;
this.car = car;
System.out.println("부모 - 매개 변수 생성자로 객체 생성");
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public String getCar() {
return car;
}
public void setCar(String car) {
this.car = car;
}
/**
* 현재 객체의 필드 값을 하나의 문자열로 반환하는 메서드
* @return
*/
public String inform() {
return String.format("%s / %s / %d / %s",
lastName, address, money, car);
}
[자식 클래스]
package dto;
/* 상속 : 부모의 코드(필드/메서드)를 물려 받아
* 자식이 자신의 코드인 것 처럼 사용
*
* 상속 키워드 : extends (확장하다)
* -> 부모 코드를 물려 받은 자식의 크기가 커지기 때문에!
*
* ** 주의 사항 **
* - 부모의 코드 중 생성자는 물려받지 못함!
*
* - 부모의 private 접근 제한자 필드/메서드는
* 상속 받긴 하지만 직접 접근 불가!!!
* -> 상속 관계여도 다른 클래스(객체)로 인식 되기 때문에
* 접근 불가
*/
public class Child1 extends Parent{
// 필드
private String notebook;
/* super() 생성자
* - super 뜻 : 상위의, 위쪽의
*
* - 현재 클래스의 상위클래스(부모) 생성자를 호출하는 구문
*
* - super()는 자식 생성에만 작성할 수 있으며
* 반드시 첫 번째 줄에 작성해야 한다!!
*
*/
// 기본 생성자
public Child1() {
super();
System.out.println("자식1 - 기본 생성자로 객체 생성");
}
// 매개 변수 생성자
public Child1(String notebook) {
// 부모 매개 변수 생성자 호출하기
super("부산 해운대구", 123456789, "모하비");
this.notebook = notebook;
System.out.println("자식1 - 매개 변수 생성자로 객체 생성");
}
// getter/setter
public String getNotebook() {
return notebook;
}
public void setNotebook(String notebook) {
this.notebook = notebook;
}
/*
* 자식 객체 + 부모 객체에 있는 모든 필드 값 출력
*/
public void print() {
// 부모 필드
// protected 필드는 상속 받은 클래스에서 직접 접근 가능!!
System.out.println("lastName : " + lastName);
// private 필드간접 접근
System.out.println("address : " + getAddress());
System.out.println("money : " + getMoney() );
System.out.println("car : " + getCar() ); // private 필드를 간접 접근
// 자식 필드
System.out.println("notebook : " + notebook);
}
/* super 참조 변수
* - 자식 객체 내부의 부모 객체를 참조하는 변수
*
* - 언제 사용해??
* -> 부모의 필드/메서드임을 확실하게 명시할 때 주로 사용
*
*/
/** 자식 + 부모 필드 정보를 하나의 문자열로 반환
* -> 성 / 주소 / 돈 / 차 / 노트북
*
*/
public String childInform() {
// return String.format("%s / %s / %d / %s / %s",
// lastName, getAddress(), getMoney(), getCar(), notebook);
return super. inform() + "/" + notebook;
}
/* 오버라이딩(Overriding) : 덮어 쓰기 / 재정의
* Over : 위에 있다, 넘어서다
* Riding : 타는 것
*
* - 부모로 부터 물려받은 메서드를
* 자식이 같은 이름의 메서드를 만들어서 덮어 쓰기
* -> 물려 받은 자식에 맞게
* 부모의 메서드를 다시 정의해아 되는 경우 사용
*
* ** 중요 **
*
* @Override 어노테이션(Annotation)
* 1) 해당 메서드는 오버라이딩 되었음을 명시
*
* 2) 오버라이딩된 코드가 알맞게 작성되었는지
* 컴파일러에게 검사하라고 지시하는
* 컴파일러 주석
*
* [오버라이딩 성립 조건]
* 1. 접근 제한자는 같거나 더 넓은 범위
* 2. 반환형, 매개 변수, 메서드명은 모두 동일
* 3. 예외처리 구문(throws)은 같거나 좁은 범위
*
* (쉽게 말해서 부모랑 똑같이 쓰는 게 제일 쉬움)
*/
// 컴파일러야 이거 잘 쓴건지 검사해줘
@Override
public void introduce() {
System.out.println("저는 Parent의 자식 Child1 입니다");
}
// Parent에게 상속 받은 toString() 오버라이딩
@Override
public String toString() {
// Child1 클래스 내부에서 toString() 호출하면
// Child1.toString()이 호출됨
// super.toString() : 부모 클래스에 작성된 toString() 호출
// -> 오버라이딩 했다고 해서
// 부모의 메서드가 덮어쓰기 되어 사라지는 것이 아니다!!
return super.toString() + "/" + notebook;
}
// final 메서드 확인하기 -> 오버라이딩 시도
// @Override
// public final void onlyParent() {
// Cannot override the final method from Parent
// -> 오버라이딩 불가 에러
}
[ Run]
package run;
import dto.Child1;
import dto.Parent;
public class TestRun1 {
public static void main(String[] args) {
// 부모 객체 생성
Parent p1 = new Parent(); // 기본 생성자
Parent p2 = new Parent("서울시 강남구 역삼동", 300, "페라리");
#결과

[Run]
// 자식 객체 생성
Child1 c1 = new Child1();
/* 자식이 부모 코드를 물려 받았는지 확인1 */
System.out.println(c1.inform());
#결과

[Run]
c1.setCar("테슬라 모델 X");
System.out.println(c1.getCar());
c1.setAddress("경기도 부천시");
c1.setMoney(Integer.MAX_VALUE);
System.out.println(c1.inform());
#결과

[Run]
System.out.println("[자식 매개 변수 생성자로 객체 생성]");
Child1 c2 = new Child1("맥북 m3 프로");
System.out.println(c2.inform() + "/" + c2.getNotebook());
#결과

[Run]
System.out.println("[protected] 확인");
c2.print();
#결과

[Run]
System.out.println("[super 참조 변수 확인]");
System.out.println(c2.childInform());
}
#결과

[Run] 오버라이딩 결과
package run;
import dto.Child1;
import dto.Parent;
public class TestRun2 {
public static void main(String[] args) {
// 부모 객체 생성
Parent p1 = new Parent();
p1.introduce();
System.out.println("-------------------------------------------");
// 자식 객체 생성
Child1 c1 = new Child1(); // 내부에 Parent 객체 존재
c1.introduce();
#결과

[Run] Object 오버라이딩 확인
System.out.println("[Object.toString() 오버라이딩 확인]");
System.out.println(p1.toString());
System.out.println(p1); // 참조 변수명만 작성해도
// -> toString() 자동 호출
#결과

[Run] Parent 오버라이딩 확인
System.out.println("[Parent.toString() 오버라이딩 확인]");
c1.setNotebook("LG Gram");
System.out.println(c1);
#결과

'BackEnd > Java' 카테고리의 다른 글
| [Java]상속(Inheritance) final 클래스 (0) | 2024.07.31 |
|---|---|
| [Java]상속(Inheritance) 오버라이딩 (0) | 2024.07.31 |
| [Java]다형성(Polymorphism) 바인딩 (0) | 2024.07.31 |
| [Java]반환형의 다형성(Polymorphism) (0) | 2024.07.30 |
| [Java]매개 변수의 다형성 (Polymorphism) (0) | 2024.07.30 |