com.eomcs.oop.ex05.a.Exam01.java

상속 - 기능 확장을 위한 문법 (oop.ex05)

03-OOP1 / 57 페이지

① 기존 코드에 계속 코드를 추가하는 방식
✔ 새 필드
✔ 새 메서드
🚨 기존 메서드 변경
기존 메서드를 사용한 프로젝트에 영향을 끼친다.
기존 코드를 손 대는 것은 위험하다.

② 기존 코드를 복제하여 새 기능을 추가하는 방식
Car 클래스

Car2 클래스 (Car 클래스 복제)
Car + α

Car3 클래스 (Car 클래스 복제)
Car + β

Car4 클래스 (Car 클래스 복제)
Car + γ

✅ 장점
기존 코드를 손대지 않는다. → 기존 프로젝트에 영향을 끼치지 않는다.

❎ 단점
원본 버그 → 모든 복사본 버그 수정
원본 기능 변경 → 모든 복사본 기능 변경

만약에 사용자가 윈도우 환경에서
OA만 붙는 게 아니라 OD OA가 붙음
맨 끝에
윈도우를 고려하지 않음
else if 추가
\r인 경우 버리게 함

실무 사례 - 고객사 별로 복제해서 커스터마이징 수행

03-OOP1 / 59 페이지

기존 코드와 새 기능을 위한 코드가 서로 밀접하게 연결되어 있다
⟹ 원본 시스템에 버그 수정을 하거나 기능 변경을 하면
⟹ 납품한 모든 시스템에 대해 각각 변경 작업을 수행해야 한다.
고객사가 100군데면 하루이틀 정도 파견해서 버그 다 잡아야 됨

03-OOP1 / 60 페이지

기존 코드가 새 기능을 위한 코드와 완벽히 분리(격리)되어 있다면
원본 코드에 버그 수정을 하거나 기능 변경을 하더라도
납품한 시스템에 원본 코드를 변경한 코드로 대체하기 쉽다.

com.eomcs.oop.ex05.c.Exam01.java

상속 - 기능 확장을 위한 문법 (oop.ex05)

03-OOP1 / 58 페이지

③ 상속을 이용한 기능 확장

com.eomcs.oop.ex05.d.Sedan.java

B extends A
B는 A를 확장한다
B : 자식 / A : 부모

A : parent class(super class)
B : child class(sub class)

super class를 변경하면 sub class에 자동으로 반영

새 클래스는 기존 코드에 영향을 끼치지 않는다!

com.eomcs.oop.ex05.d.Exam01.java

상속 예 - oop.ex05.a/b/c/d

03-OOP1 / 61 페이지

com.eomcs.oop.ex05.d.Score2.java

🔹 오버라이딩(Overriding) = 메서드 재정의
수퍼 클래스로부터 상속받은 메서드를 서브 클래스의 역할에 맞게 재정의하는 것
super class의 메서드 형식(메서드명, 파라미터, 리턴타입)이 같아야 한다.

메서드 형식(메서드명, 파라미터, 리턴타입) → method signature
✔ C/C++에서는 function prototype 이라고 한다.

@Override 붙이기
컴파일러에게 재정의를 제대로 했는지 검사해 달라고 서비스를 요청하는 명령

com.eomcs.oop.ex05.e.A.java

com.eomcs.oop.ex05.e.Exam01.java

상속 예 - oop.ex05.e

03-OOP1 / 62, 63 페이지

com.eomcs.oop.ex05.e.Exam01.java

🔹 메서드 찾는 순서
레퍼런스의 클래스부터 찾기 시작해서 수퍼 클래스로 따라 올라가면서 찾는다.

코드를 갖고 있는 게 아니라 사용권만 갖고 있는 거

com.eomcs.oop.ex05.e.Exam02.java

메서드를 호출할 때는 클래스 상속 관계에 따라
레퍼런스의 클래스에서 시작하여 상위 클래스로 찾아간다.

호출할 때 따라 올라가야 되기 때문에
객체 지향 프로그래밍 언어로 짜는 게 속도가 느리다.
실행 속도가 다소 떨어지더라도 소스 코드의 유지보수를 더 쉽게 하자는 목적으로 나온 게 객체 지향 프로그래밍 문법

상속 예 - oop.ex05.f

com.eomcs.oop.ex05.f.Exam01.java
상속 - 클래스 로딩과 인스턴스 생성 과정

UML에서는 변수명 : 타입
A 클래스 - v1 : int
B 클래스 - v2 : int

클래스가 로딩될 때 스태틱 초기화 블록은 실행된다.
클래스가 로딩되는 경우
클래스 멤버(필드와 메서드)를 사용할 때
해당 클래스의 인스턴스를 생성할 때

B obj = new B();

① A 클래스 로딩 (Method Area) → 스태틱 블록 실행
② B 클래스 로딩 (Method Area) → 스태틱 블록 실행
③ A의 인스턴스 변수 생성 (Heap)
④ B의 인스턴스 변수 생성 (Heap)

수퍼 클래스의 인스턴스 변수부터 생성한다.

B obj2 = new B();

① A의 인스턴스 변수 생성 (Heap)
② B의 인스턴스 변수 생성 (Heap)

상속 예 - oop.ex05.g

com.eomcs.oop.ex05.g.Exam01.java

C obj = new C();

① A 클래스 로딩
② B 클래스 로딩
③ C 클래스 로딩
④ A 클래스의 인스턴스 변수 생성
⑤ B 클래스의 인스턴스 변수 생성
⑥ C 클래스의 인스턴스 변수 생성
⑦ C의 생성자 호출

수퍼 클래스의 어떤 생성자를 호출할지 지정하지 않으면 컴파일러는
다음과 같이 수퍼 클래스의 기본 생성자를 호출하라는 명령을
생성자의 첫 줄에 추가한다.

서브 클래스 생성자의 첫 문장에서 수퍼 클래스의 기본 생성자를 호출한다

호출은 거꾸로 올라간다
실행은 아래로 내려온다

서브 클래스에서 수퍼 클래스의 생성자를 첫 번째 문장으로 실행하기 때문에

A 클래스의 생성자가 제일 먼저 호출된다고 착각함

invokespecial 특별한 호출

자바의 모든 클래스는 java.lang.Object의 자손 클래스

자바스크립트의 캡처링 타켓 버블링과 비슷..

com.eomcs.oop.ex05.g.C.java

수퍼 클래스 생성자를 호출하는 명령은 반드시 생성자의 첫 문장으로 와야 한다.

만약 개발자가 수퍼 클래스의 생성자를 호출하는 명령을 작성할 때
그 전에 다른 코드가 있다면 컴파일러는 오류를 발생시킨다.
Constructor call must be the first statement in a constructor
따라서 수퍼 클래스 생성자를 호출하는 명령은 반드시 첫 문장으로 와야 한다.

자바에서 제공하는 라이브러리
소스 파일이 아니라 클래스 파일이다!

java -cp bin ExamTest

javac src/ExamTest.java

javac -cp classes src/ExamTest.java

import com.eomcs.oop.ex05.x.C;

처음에 C 클래스 작성한 사람이 com.eomcs.oop.ex05.g.C

반드시 그 패키지 밑에 놓여 있어야 됨

클래스를 구분하는 유의미한

g 패키지에 소속되었다고 정했으면 반드시 그 패키지 밑에 있어야 됨

상속과 수퍼 클래스 생성자의 관계

com.eomcs.oop.ex05.h

다른 사람이 준 클래스를 기능 확장할 수 있음

확장 못 하게 막고 싶다
클래스 앞에 final을 붙이면 컴파일러가 컴파일 안 해줌

대표적인 게 바로 String

The type String2 cannot subclass the final class String

String 클래스는 final 클래스라고 sub class 못 만든다고 나옴

어떤 생성자를 호출할지 지정하지 않으면 수퍼 클래스의 기본 생성자를 호출
컴파일러가 자동 삽입

A 클래스의 기본 생성자를 호출하는 코드를 삽입한다.

FileReader 클래스에는 기본 생성자 없음

다중 상속

자바는 다중 상속을 지원하지 않는다.

C obj = new C();

여러 클래스를 동시에 상속받으면 변수나 메서드에서 충돌이 발생할 수 있다. (이름이 같은 경우)
⟹ 그래서 자바는 다중 상속을 허락하지 않는다.

상속 : 전문화 / 일반화

oop.ex05.k / l

🔹 전문화(specialization)
수퍼 클래스를 상속 받아 기능을 덧붙여서 좀 더 특별한 역할을 수행하는 서브 클래스를 만드는 것
예) FileReader2

🔹 일반화(generalization)
서브 클래스들의 공통점을 추출하여 더 일반적인 용도의 수퍼 클래스를 정의하는 것

메서드 이름은 다르지만 같은 기능을 수행
추출해서 수퍼 클래스를 정의
Car 클래스 정의
서로 다른 메서드명은 적절한 이름으로 통일

Car ← 일반적인 역할을 정의 (일반화)

Car는 직접 사용하려고 만든 클래스가 아니다.

Sedan과 Truck의 공통 기능을 보다 쉽게 관리할 목적으로 만든 클래스다!

이것을 막는 문법이 "추상클래스" 이다.

상속 : 일반화와 추상클래스

03-OOP1 / 70 페이지

com.eomcs.oop.ex05.m

generalization을 통해 정의한 수퍼 클래스는 그 자체로 직접 사용할 목적으로 만든 클래스가 아니다.
이런 클래스는 실수로 인스턴스 만드는 것을 막을 필요가 있다.
이런 목적으로 등장한 문법이 '추상 클래스'이다.

abstract 키워드 넣으면 됨

abstract class 클래스명 {...}

추상 클래스는 인스턴스를 만들 수 없다.

추상 클래스의 인스턴스를 만들려고 한다면 컴파일 오류가 발생할 것이다.

상속 : 추상 클래스와 추상 메서드

03-OOP1 / 71 페이지

서브 클래스의 역할에 맞게 재정의해야 할 메서드라면
굳이 수퍼 클래스에서 정의할 필요가 없다.
단지 서브클래스에 run() 이라는 메서드가 있어야 한다고 선언만 하면 된다.
메서드 형식만 정하는 것 ⟹ 추상 메서드

🔹 추상 메서드
서브 클래스의 역할에 맞춰서 구현해야 하는 메서드인 경우,
메서드 시그너처(리턴타입, 메서드명, 파라미터)만 작성한다.
서브 클래스에게 구현을 강요한다.
메서드의 몸체를 만들지 않기 때문에 일반 클래스에는 추상메서드를 둘 수 없다.
오직 추상클래스(또는 인터페이스)만이 추상메서드를 가질 수 있다.

0개의 댓글