com.eomcs.oop.ex05.a.Exam01.java
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
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
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
03-OOP1 / 62, 63 페이지
com.eomcs.oop.ex05.e.Exam01.java
🔹 메서드 찾는 순서
레퍼런스의 클래스부터 찾기 시작해서 수퍼 클래스로 따라 올라가면서 찾는다.
코드를 갖고 있는 게 아니라 사용권만 갖고 있는 거
com.eomcs.oop.ex05.e.Exam02.java
메서드를 호출할 때는 클래스 상속 관계에 따라
레퍼런스의 클래스에서 시작하여 상위 클래스로 찾아간다.
호출할 때 따라 올라가야 되기 때문에
객체 지향 프로그래밍 언어로 짜는 게 속도가 느리다.
실행 속도가 다소 떨어지더라도 소스 코드의 유지보수를 더 쉽게 하자는 목적으로 나온 게 객체 지향 프로그래밍 문법
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)
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() 이라는 메서드가 있어야 한다고 선언만 하면 된다.
메서드 형식만 정하는 것 ⟹ 추상 메서드
🔹 추상 메서드
서브 클래스의 역할에 맞춰서 구현해야 하는 메서드인 경우,
메서드 시그너처(리턴타입, 메서드명, 파라미터)만 작성한다.
서브 클래스에게 구현을 강요한다.
메서드의 몸체를 만들지 않기 때문에 일반 클래스에는 추상메서드를 둘 수 없다.
오직 추상클래스(또는 인터페이스)만이 추상메서드를 가질 수 있다.