상세 컨텐츠

본문 제목

다형성(interface) 정리 (java)

수업 일지/Java

by NayC 2021. 4. 8. 08:47

본문

728x90

1. 캡슐화 알고 있다.

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

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

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

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

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

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

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


(35-37일 다시 새롭게 만들면서 복습) 

 

상황

 

만약 저 프린트 로고가 마음에 들지 않아서, 다른 사람이 고칠 수 있도록 해주게 하고 싶을때. 

 

코드의 일부분을 잘라낼 수 있도록 하겠다.

- 근데 그러면 전체적으로 미완이기에 오류가 나게 될 것 ... 

-> 그래서 저 다른 애들이 없어도 돌아가게끔 임시적으로! 장치를 마련해둔다. + 꽂을 수 있도록 해주고/접근할 수 있도록 해주고

 

약속(인터페이스)을 구현 ----- 약속을 정의 (정의하는 쪽은 제품 쪽!) 

 

장점

- 협업 가능

- 지금 만들지 않아도 차후에 만들 수 있다

- 다양성 제공 가능 (다양한 회사, 다양한 제품 등)

 

이런걸 '다형성'이라고 한다.

 

추상화는 - 자식에게 위임하는거라면

다형성은 - 인터페이스를 사용하려는 모든 애들이 구현할 수 있도록 한 것


1. 성적 출력 디자인을 뽑아내보자. 

banner.print();를 만들어주자

- printBanner()와 printEnd(---- 이런 부분)을 가지고 있는 

인터페이스 생성 (커서 가져다대면 create interface가 나옴)

그리고 인터페이스 안에서 정의

 

인터페이스에서는

'약속'을 위한 목록이기에 public, private 쓰는게 무용지물

-> 구현하는게 아니기에!!!! (그래서 int 이런것도 이상함)

약속!을 위한 것. 

약속으로 수반되어야 할 목록을 올려주는 것이다. 

 

인터페이스는 무조건 public

 

2. 어딘가...banner를 구현한 객체가 있을것. 구현했다고 치고~ main함수를 완성해보자. 

(다른 것들 작성 전에 main함수부터도 적을 수 있는 것)

2,1 번을 뒤바꾼게 더 자연스럽게 이해되기는 한당

 

인터페이스를 구현하겠다(implements)

 

2.1 YBMBanner를 구현해보자

2.2 구현한걸 꽂아서, 자연스레 녹여들여 출력해보자

구현한 ybmbanner를 setBanner로 꽂아야 자연스럽게 같이 출력되는 것

 

그리고 private Banner banner를 한 이유는,

banner.print()

banner.printEnd()를 하기 위해

 

질문 

- banner.print()에서 인터페이스 생성을 눌렀는데 소문자로 banner였는데 위에는 지금 억지로 Banner로 고쳐준거...

  그리고 여전히 Banner는 빨간줄인데 실행은 잘 됨... 이게 why?? 

-> private Banner banner의 Banner에 커서 대고 create interface 하는거였음 

 

cf) 인터페이스여도 부모형으로도 참조 가능하다.  

 

3. 이전에 추상화로 해줬던 onPrint도 인터페이스로 가능한거 아닌가? 그렇다. 해보자. 

(보통 인터페이스로 구현하는듯 하다)

 

질문 

- extends를 하지 않고도 구현 가능하다는게 무슨 말이지? (뭐가 더 편리하다는거지?)

onPrint를 인터페이스로 어떻게 구성하는거지? 


인터페이스는 class 아무데서나 구현해도 가능하다는 것 

- 중요한 것은 인터페이스 구현을 하는 것. 

-> 인터페이스 구현을 위해 굳이 따로 class를 만들지 않는다. 

 

다중상속이란건 C++에서나의 얘기.

자바에서는 여러 class를 받는다는건 말이 안되는 소리 (절대로 안된다. 오로지 한 개다.)

 

1. Banner 구현한다고 새롭게 YBMBanner 만들지 말고, YBMExam에 구현해보자.

YBMExam에 구현을 해줬는데 아까랑 결과가 같은 이유 

-> main을 고쳐야지!

1) YBMBanner라는 class를 새롭게 만들지 않고 지금 하는게 목표였으니 YBMBanner, ybmBanner들 삭제

 

// 

 

 

// 다시 상황 정리 : exm을 이용해서 YBM 제품을 만들겠다는 것

(패키지를 나누어줬을 때를 또 배워보기 위해 나눠주었다)

 

1.1 오류가 뜬다. 왜일까. (★)

패키지를 나눠줘서 ExamConsole 아래 빨간줄 그어지면서 imort하라고 뜨는데 자연스러운거니 import ~ 

main 함수를 한 줄 한 줄 읽어보자.

 

12번째줄) Exam exam = new YBMExam(1,1,1,1,1);

- YBMExam 에 1,1,1,1,1을 넣어 만든 것들을 / exam이 가리키고 있다. (그리고 exam의 객체 형식은 Exam)

 

13번째줄) ExamConsole console = new YBMExamConsole(); 

- YBMExamConsole 파일을 들여다보면 ExamConsole을 상속(extends)하고 있기 때문에 

-> new 생성을 하면 사실 2개의 객체가 만들어지는 것 (부모거, 자기거)

그런데 console 의 객체 형식은 ExamConsole이라 console은 ExamConsole 형식것만 가리키게 된다. 

 

15번째줄) 이건 이전 내용인데 다시 복습 겸 이미지 첨부 (초기화 위해 DI 배울 때) 

이게 '지금' 코드에서도 오류 없이 돌아가는 이유는 exam의 객체 형식은 Exam이고, setExam에서 받아야 하는 데이터 형식도 Exam인데 잘 쓰였기 때문임. 

 

반면, 

16번째줄) 객체 형식이 잘못되었다. 

- 부모 형식으로도 쓸 수 있다고 막 쓰면 안되는거였음... 

cf) setBanner의 자리가 ExamConsole에 있는 이유는 private로 잡힌 멤버들의 '초기화'를 위해서임

- 여기서 직접 생성해줘도 됨

 

// 잘 나왔다 :) 

 

 

이건 set함수 이용하지 않아보려고 내가 해본건데...  Exam이 객체 형성이 안되어서 직접 생성이 안되네. set방식밖에 없는듯? 

 

1.2 새로운 오류를 만나보자. (정말 아무곳에 interface 구현은 노노 ㅎㅎ)

현재 상황) 인터페이스는 어느 클래스든 상관없이 구현만 하면 된다고 해서 YBMExam에 구현을 해줬지. 

근데 문제가 하나 있다.  -> 장소가 적합한지 생각해야함 

- 정말 아무데나 들어가는건 문제

- YBMExam은 데이터 있는 곳인데 갑자기 프린트를 구현해버렸지. (이럴거였으면 굳이 YBMConsole 따로 안떼어놨을 것)

-> 콘솔 있는 쪽이 더 좋음. 그래서 옮기자. 그리고 implements Banner는 콘솔 있는 쪽에 해주고

 

// 뿌듯....함을 느끼는게 맞을까?

 

YBMExam에서 인터페이스 구현했던걸 YBMExamConsole로 옮겨준다.

그럼 위와 같은 오류가 뜸 (같은 문제~) 

 

그런데 고쳐줘도 ... 결과값이 제대로 나오고 있지 않음.

 

ExamConsole 클래스에 print함수가 있는데 그것을 재정의 해버리는 꼴이 되어서 YBM성적출력 값만 나오게 된 것

(override가 우선순위를 가지고 감)

 

// 인터페이스 아무 클래스에서 구현만 하면 된다고 하더니 오류가 발생한 것.

 

2. 인터페이스 구현을 위해 클래스를 정의하는 방법이 확장. (클래스 안에 클래스를 정의)

클래스 '안에' 클래스를 만들고 implements Banner를 해준다. 

- 그럼 밖의 멤버와 충돌 날 일이 없음. private도 쓸 수 있고

 

요지는 인터페이스 위해 굳이 클래스 새롭게 만들지 않고 이렇게 사용한다는 것

 

cf) setBanner에 빨간줄 그어지는건 정상 (아래 2.3에서 수정해줄거다) 

 

2.1 outer 클래스의 private 멤버를 inner 클래스가 쓸 수 있을까? 그렇다. 

outer 클래스의 private 멤버를 inner 클래스가 사용할 수 있되, 두 개가 같이 전달됨

1) 밖의 YBMExamConsole (outer class의) this 

2) 자기 울타리 XXX의 class의 this

-> 그래서 그냥 this만 쓰면 애매해진다. 

2.2 class XXX의 선언 과정

 

그런데 5번에서는 public한 것 때문에 오류가 남. (안하는게 맞는듯. 이유 알기)

2가지 방법

1. 

2.

import를 하지 않으면 XXX 앞에 아우터 클래스(YBMExamConsole)의 이름을 명시해주어야 한다. 

 

2.3 XXX의 객체를 만들어주는 조금 특별한 방법

이너 클래스는 아우터 클래스를 통해서 만들어져야 함
객체가 가지고 있는 new라는 연산자를 사용해서 이너 클래스를 만들자

 

setBanner에 꽂아넣게 될 클래스가 아우터 클래스 안에 있는 이너 클래스임

cf) priavae int a 값 주는 연습한다고 썼다가 주석을 안해놔서 위에 사진들에서는 실행이 안됐는데, 주석 처리를 하면 이렇게 정상적인 결과값들이 나올 것 ~ 


3. YBMExamConsole 만든 사람이 초기화를 하게 해보자. (이게 일반적)

1) 생성자 만들고

2) 초기화 

 

지금 파일이 달라졌으니까 console. 대신 this로 바꿔줘야 함

근데 this 생략 가능해서 써보면 굉장히 그냥 일반적인 new 쓰는 것처럼 보임

-> 앞에 this 가 생략되어있구나!!! 를 꼭 인지해야한다. 

 

(헷갈리게 생긴 끝판왕 3번째...)

앞에 YBMExamConsole도 지워줘도 되서 XXX x = new XXX();만 써도 되는데 이건 정말 마치... 기본 생성처럼 생겼는데, 

XXX 생성하는 기본적인게 아니라는거 (지금 우리는 inner class인 XXX의 객체를 만들어주고 있다) 

 

 

(다시 위에서 하던거로 돌아와서) 

2.1 / 4.  outer 클래스의 private 멤버를 inner 클래스가 쓸 수 있을까? 그렇다. 

//


cf) 생성자, 초기화

변수 선언 해줬고, 값을 넣어주는데 계속 에러가 나길래 뭐가 문제인가 헸는데 

이렇게 해줘야 했다. 

 

Q. 이건 왜 오류가 날까 

 


 

4.1 만약 inner class의 멤버 말고 outer class의 변수를 사용하고 싶다면? 

그냥 this를 쓰면 XXX거

-> 밖의 거를 쓰고 싶으면 식별자를 붙여준다. 

여기서 this를 안붙여주면 에러가 났다.

setBanner(x) 아래 

a=3; 을 넣었으면 3이 나왔을 것


5. 배너용으로 한 번 쓸건데 굳이 class를 만들 필요가 있을까 -> 메소드 안에 클래스를 넣어버릴 수 있다. 

딱 한 번 setBanner에 꽂아주기 위해 만든 것. 

5.1 class 없애버리자! -> ( ){ };

() 만 하면 안되는데 (인터페이스를 객체하는건 안되기에)

{} 붙이면 된다! (익명/무명 클래스를 구현하겠다는 것)

 

{} 중괄호 뒤에 ; 있다는 점

엄청난 차이가 있는 것

class 없이 인터페이스를 구현해줌

 

MJ님 표현 참고

 

 

 

 

 

 

 

728x90
반응형

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

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

관련글 더보기