상세 컨텐츠

본문 제목

추상화 정리 (java)

수업 일지/Java

by NayC 2021. 4. 8. 08:46

본문

728x90

1. 캡슐화 알고 있다.

2. 두 개 이상의 캡슐이 만들어질텐데, 조립할 줄 안다. (has A)

- 멤버로 꽂아넣고, 만드는 방식

3. 남이 만든 클래스를 상속받아서 (오버라이드) 쓸 수 있다. (is A) 

<-> 반대로 내가 클래스를 만들었는데 여러 자식을 만들어야 할 것 같음. 공통 분모를 잘 사용할 수 있도록

1) 꼼수. 대문 만들어주기 (onPrint()같은거)

2) 자식이 내거 쓰고자하는게 있다면 재원 getter로 만들어줘서 쓰게 하기

3) 만약 못쓰게 하려면 abstract class 할 수도 있고 / 자식이 꼭 쓰도록 강요하려면 abstract method


(32일~34일 다시 새롭게 만들면서 복습) 

 

추상화 - 캡슐의 공통분모를 잘라내는 것 (=공통분모의 캡슐화)

ex) 클래식 (자동차), 세단 (자동차), suv (자동차)... 가 있다고 할 때 공통 분모가 있을 것 - 기계, 자동차,... 

 

A 객체, B 객체의 공통 분모를 O라고 하면

- O에 올려다 놓고

- 각각 A, B는 공통되지 않은 것만 가지고 있게 함

 

근데, 탑-다운만 가능한건 또 아니다.

만들다보니 공통분모가 있을 때 고치는 작업이 일어날 것

그럼 기존 코드를 뒤집는(?) 일이 일어남 = 리팩토링 / 고도화 작업 (당연히 이런 일이 일어날 수 밖에 없다~)

 

1. 상황) 뉴렉고등학교와 YBM 고등학교가 국,영, 수 과목을 추상화 

우리가 만드는 것은 이것! 추상화! 뼈대!

 

2. 추상화 class는 실체화되지 못하도록 한다. abstract 

-> new가 안되도록 막아줌

 

Q. 추상클래스란 instant를 꼭 써야하나. (= 객체화 해야 할 필요도 있을까?)

- 추상 클래스 자체만으로도! 사용할 수 있도록 할 때는 abstract를 붙이지 않는다. 

- 반드시 객체화되지 않는건 아니다

 

'추상이다 아니다'는 마음속에 개념속에 있는 것

abstract가 없다고 추상이 아니라고 또는 추상이라고 할 수 없음. 

 

2.1 Exam 기능들을 YBMExam 고등학교가 쓰도록 해보자. 

 

Exam의 기능들을 YBMExam 고등학교가 쓰려고 extends 해주고, 객체도 만들어줬는데 문제 발생

Exam의 공통 분모 애들로만 결과가 나온다. (total은 국영수 1+2+3 = 6, avg는 6/3=2) 

-> 재정의 해줘야 할 필요가 있다

 

2.2. total과 avg를 YBMExam고등학교에 '알맞게' override 해준다. 

그냥 crtl+space 눌러서 override 해줬을 때는 return super.avg() 인 상태였음. 이걸 '알맞게' 고쳐야 원하는 값이 나온다는거~~! 

 

3. abstract 기능 심화 

NewExam의 avg도 this.total()/4.0f로 바꿔줘야 함~ 

 

Exam의 avg는 누구도 안쓰는데 굳이 구현을 해야하나?

-> 코드 지우자! 

-> 그리고 각자 고등학교가 각각 쓰도록 하자!  // 노노~~ 워워~~ 

Exam exam 참조하기 위해서는! 기능이 있어야 한다. 

 

각각 고등학교에서 안쓰는 기능 버리기도 그렇고~ 살려두기도 그렇고~

-> 구현을 없애버림! 

 

NewExam의 avg도 this.total()/4.0f로 바꿔줘야 함~ 

abstract 붙여서 "일부러 뺀거야~ 나를 상속하는 얘들이 만들거야~" 라고 알려줘야 한다. 

 

그럼 이렇게 자식에게 책임감이 부여된다.

 

3.1. 각 고등학교의 avg를 담는 배열을 하나 만들어보자.

 


1. ExamConsole을 따로 빼서 추상화를 해보자.

 

1.1 데이터 있는 쪽(Exam)에서 우클릭 > source > getter & setter 형성

 

cf)

getter - private 멤버롤 외부에서 읽을 수 있도록 해주는 것

setter - 외부에서 값을 줄 수 있는 것

 

보통 클래스의 멤버 변수는 private로 접근제한자를 설정한 후 
getter를 통해 - 은닉된 변수의 값을 읽어들이고
setter를 통해 - 은닉된 변수에 값을 넣는다. 

maktooob.tistory.com/35

 

-> 근데 출력이 안됨.

 

여기서 exam은 객체를 가지고 있지 않는 상태 (Exam exam으로 참조변수로만 있는 것) 

-> 이용하려면 객체를 만들어줘야. 2가지 방법. 객체를 자기가 만들거나, 남이 만들어서 넘겨주거나 

 

2. DI 개념 등장 배경

(Exam 파일 수정 필요. abstract 했었던걸 예제를 위해 풀어준다.)

2.1 Constructor DI (생성자 DI)

6번째줄 기본 생성자 지워도 무방

ExamConsole에서 exam 없이는 의미 없으니 바로 exam을 갖게 하기 위해서! 일부러 기본 생성자 지우는 느낌으로

 

이렇게 직접 했을 때는 L 10번째줄에 exam이 없어도 정상적으로 돌아감!

 

R 6번째 줄이 없으면 무조건! 꽂아 넣어야 하는거고  (꽂아 넣게만! 하는 것/DI가 꼭 필요한 것)

2.2 Setter DI

getter & setter 생각 없이 쓰면 안 됨

- get은 내가 가지고 오려는 곳에서

- set은 내가 넣어주려는 곳에

-> 여기서 exam 에 1,2,3을 넣어주려는 곳은 ExamConsole이니까 이곳에 setExam을 넣어야 하는 것

 

3. 고쳐 쓰는 첫번째 방법 - 추상화 (abstract) 상황에 맞게 수정하기

abstract class

avg도 abstract

total도. 대신에 baseTotal 줄 수 있음

(이름은 마음대로 명명한 것. 그냥 자식들이 total 계산 때 사용하라는 의미에서 baseTotal)

 

Exam 파일이 abstract 되어서 Program에서 new Exam 하면 안 됨

 

문제 발생

baseTotal 기능은 자식에게 보이려 했던 기능인데, 자식이 아닌 곳에서도 기능이 보임.

-> protected (자식만 쓸 수 있도록) 

-> 그리고 나서 다시 하면 노란색 동그라미가 뜬다. (쓸 수 없다는 것) 

 

4. 고쳐 쓰는 두 번째 방법 - 인터페이스 (추상화의 대안으로 등장)

위의 방법에서는 계속 YBMExam 5과목을 넣어도, NewExam 4과목을 넣어도 국, 영, 수만 출력해낸다.

-> ExamConsole에 국, 영, 수밖에 없기 때문에! 

 

Exam 은 다른 자식을 가질수도

-> 그래서 Program에 어떤 객체가 꽂아질지 모름

-> 이 경우 ExamConsole의 프린트 기능이 부모 객체에 따라 유연하게 대처할 필요가 있음

 

 

확장된 과목에 대한 함수를 만든다.

근데 자바는 함수만! 꽃아 넣는게 불가능. class 안에 구현해야 한다. 

-> class로 만들고 객체? 전달하는 방식으로 사용

 

cf) '직접' YBMExamConsole class 새로 만드는게 가장 속편하지. 근데 소스 복붙하고, ExamConsole에서 private Exam exam; 되어 있는걸 풀어줘야 하고.... 이것저것 바꾸어야 해서 엉망징창. 

 

4.1 부모는 확장하는 자식이 코드를 꽂아넣을 수 있도록 장치를 마련해둔다.

자식에게만 노출되는 함수를 만드는 것

#onPrint();

- 자식이 추가적으로 쓸게 있으면 정의해라. 그럼 내가 호출해줄게. 

- 부모가 쓸게 아니라서 부모에서는 아무 (구현) 코드도 없음

 

이미지는 NewlecConsole이지만, 나는 YBMExamConsole로 예시를 들 예정

1) 메인 함수에서 print 함수를 읽으면

2. ExamConsole의 print() 함수로 가서 순서대로 읽을 것

3. onPrint() 함수를 만나면 자식의 onPrint() 함수를 호출하고 (이 이미지상으로 컴퓨터 과목이 추가가 된다)

4. 다시 순서대로

 

4.2 YBMExamConsole을 만들어서 Toeic, aa 과목을 추가해서 출력해보자

onPritn()를 Override한다는 점! 

 

여기서 Toeic,aa 값은 콘솔에 직접 100이라고 입력해서 단순히 나온 값

 

오류 이류 : exam이 not visible 하다고 나옴 

(ExamConsole에서 Exam exam이 private로 되어 있어서)

-> 자식이 나를 사용하도록 도구 잘 제공하기.

 

ExamConsole에서 get을 해주자 

- 내부에서 Exam exam이 private인데 YBMExamConsole에서 exam.getToeic 이렇게 해줄 수 있도록

(만약 자식만 쓰게 하고 싶으면 앞에 protected 해주던지 하는건 선택)

- 9번째줄을 꼭 해줘야 진정 exam. 하고 쓸 수 있는 것

- 그리고 getToeic만 쓰면 안 됨. () 까지! (함수를 가지고 오는거니까 당연한 소리) 

 

문제는, 

확장한 과목에 대해 exam. 사용불가

-> YBMExam으로 변환해야함 

 

Exam exam = getExam();

YBMExam exam = (YBMExam)getExam();

 

ExamConsole 파일에서 getExam()을 통해서 Exam을 받았지. 

그런데 이 getExam()을 가져올 때 자식에게 맞게 형변환을 해서 쓴다. 

 

참조변수의 형식을 바꾸어주는 것

출처 : 34일 수업

재사용용 - ExamConsole에서

1. 원래 Exam exam은 private로 여기서만 쓰이는데, 자식들도 exam 활용해서 사용가능하도록 getter해주고

(서비스를 이용하는! 사람 입장에서 생각. 서비스를 이용하는 자식들 입장에서는 get해오는!거니까)

2. 그래서 exam 사용 가능해졌찌

3. 그런데 getExam 해서 가져올 때는, 자식에게 맞게 형변환 ("형변환해서 쓰는게 당연하죠")

 


5. 입력도 해보자. 

부모인 ExamConsole에 input() 함수 생성

input()함수를 생성하면 메소드를 YBMExamConsole에 생성하라고 나오는데, 그러면 재사용을 하지 못하니까

ExamConsole에 생성해서 Override를 해주기로 하자.

 

cf) 우선 input() 함수 override 전에 헷갈렸던 set 이유를 살펴봄

입력을 한 거를! exam에다가 넣어줘야지 -> 내가 구현한 코드들이 돌아가니까 set을 저렇게 해주는건 정말 당연한 것

 

여기서도 형변환을 해줘야한다. 

getExam이라는거! 

여기서 exam을 가지고 온거니까. (정신 똑바로 차리고 해야함) 

 

여기서는 super.input()을 생략하면 안 됨 (그러면 국, 영, 수가 안나오게 됨)

그리고 실행 순서상 맨 위에 두기! 

 

 

 

 

 

728x90
반응형

'수업 일지 > Java' 카테고리의 다른 글

다형성(interface) 정리 (java)  (0) 2021.04.08
객체지향 정리 (java)  (0) 2021.04.07
따옴표 정리  (0) 2021.03.12
숙지를 위한 연습 문제들 (java)  (0) 2021.03.11
변수 정리  (0) 2021.03.08

관련글 더보기