<오전 문제 간단 리뷰>
-실제로 오늘 오전문제 Canvas에서 함수 명(drawBoard : X)도 엄밀히 잘 생각해보자
-자바는 언더바 지양해야함, 구분은 대소문자로 해야한다. (언더바는 주로 파이썬 : 스케이크표기법)
I. INTRO : 지난시간복습
객체지향의 필수요소들 캡슐화 상속 다형성
구조적프로그래밍은 그냥 함수 정의만 하면 됨, 자르는 기준없음
함수 4가지 장점만 알면됨
나누는건 객체지향에서 연습하면 됨
II. 캡슐화 :역할을 가지고있는 영역
1. 캡슐화
(1)캡슐화
캡슐화란 캡슐을 만드는 것임
기존에는 캡슐이 없는데 만드는 것임, 여기서 캡슐이란 '구조화된데이터' 그것을 사용하는 '함수'를 묶은것이다
객체지향은 실세계 표현을 코드에 묻어나게끔 하는것이다.
구조화된 데이터가 없는 것은 메소드를 가질 수없다.
기능을 뽑을 때에는 데이터 구조가 있어야한다고 볼수있으나, 그렇지않다
캡슐이란 역할(데이터구조랑은 관계 낮음)이 있는 코드의 구성요소을 가지고 있는 것이다.
물리적이기 보다는 논리적 이론적 문과적 마인드로 프로그램을 보아야한다.
(2) 캡슐을 깨뜨리는 행위란?
캡슐이 깨지다. 라 함은 바깥캡슐 변화가 다른 캡슐에 영향을 준다.
이를 해결하기 위해서 은닉성을 위해서 접근제어자를 이용한다.
캐슐이 깨뜨리는 경우가 무엇인가? 구조가 바뀔때를 의미한다.
기존 멤버변수들을 새로운 구조를 만들경우(즉 구조는 바뀌지만 구성은바뀌지 않음) 캡슐외부의 다른곳에도 일일이 수정하는등의 수정의 범위가 넓어진다 (아래코드)
(3) 객체 초기화
일반적인 멤버변수에는 바로 값을 넣지않는다. 단순한 뼈대, 청사진에 불과한 것이다.
값은 생성자에다가 인스턴스의 변수(this)에 넣어준다. (아래자세히)
2. 메소드 오버로드
동일함수에 대해서 인자(매개변수)가 다르면 오류가 C시절에는 발생했다. 이당시에는 같은이름은 못쓰게했다
당시에는 이름만 비교함. 자바는 이름과 인자까지 봄
적재량이 과하다 오버로드 이다. 이런거 처럼 원래보다 더 과적(over / load)
인자적은것은 기본값으로 출력한다./ 인자많은것은 오버로드
오버로드 있다는 것은 중복이 있다는 의미이다. 그러므로 오버로드는 코드를 줄이는 방법을 찾아야한다.
이는 쓰는 사람으로 하여금 사용권을 줄수있다.
<메인함수>
examl.printExam(); //기본메소드 호출
examl.printExam('*'); //오버로드 메소드 호출
examl.printExam('=', 50); //오버로드2메소드호출
<Exam class> : 오버로드 시 코드를 줄이는 방법
//기본메소드
public void printExam() {
printExam('-'); //기본값을 가지는 함수
}
//오버로드 메소드1
public void printExam(char ch) {
printExam(ch, 30);
}
//오버로드 메소드2
public void printExam(char ch, int length) {
System.out.printf("점수는 ");
System.out.print(" 국어: " + kor1);
System.out.print(" /영어: " + eng);
System.out.print(" /수학: " + this.math);
System.out.println();
for(int i = 0 ; i< length ; i++)
System.out.printf("%c", ch);
}
위와같이
3. 생성자 오버로드 (오버로드 된 생성자)
초기화시 레퍼런스는 null / 값은 0
모든클래스는 기본생성자가 있다.
public Exam () { //exam 형식의 객체만 나를 호출할수있다! (한정사)
// Exam(100,100,100); //이건 불가능
//왜냐하면 생성자는 이름이 없다.
this(100,100,100); //인스턴스에다가 해야함
kor1 = 0;
}
public Exam (int kor , int eng, int math) {
this.kor1 = kor;
this.eng = eng;
this.math = math;
//이경우 this를 쓰지않으면 양쪽다 지역변수이다.
//이 경우 좌측은 인스턴스에 대한 변수로 바꾸어주어야
}
위의 기본생성자에서 오버로드생성자를 호출할 때 메소드가 아니고, 이름도 가지고 있지않는다.
따라서 이클립스는 정의되지 않은 메소드라고 오류를 발생시킨다.
생성자는 결국 인스턴스가 생성될때 초기화 되는 것이다.
인스턴스(this)에 대한 오버로드 생성자 호출을 하는 방식으로 접근해야 바람직하다.
(우선순위 유의)
III. 상속
1. 들어가며
간단하게 보면 캡슐 하나하나 만들면 어플리케이션이다.
레고 블럭하나하나 자체는 의미 없음 엮어야 의미가 있음 엮는것을 관계를 만든다.
캡슐 간 관계를 만들면 어플리케이션이다.
부담을 줄여야한다. 모든 프로그램은 메인함수에서 시작한다.
실제 메인함수 코드에서 다른곳으로 성적 출력입력하는 코드가 갔다.
이경우 메인함수가 가벼워졌다. 즉 캡슐로 나옴으로서(캡슐이 역할을 담당한다)
무게감이 줄어드는것이 아니라 역할을 나누는 것이다.
2. UI와 데이터 서비스는 분리하는것이 바람직하다.
(1) 객체화 혹은 의존객체
캡슐에 어떤기능이있는지를 알기위해 구조를 도식화 하는것이 좋다
점 화살표는 객체화해서 쓰고있다는 의미( main ....> Exam)
이른바 종속객체 의존객체(dependency : 종속)라고 한다.
그러나 부품객체(부속물)이라고 부르는것이 쉽다.
(2) 클래스간 결합하기
최근 우리는 file, 콘솔 API를 자주이용한다. 콘솔기반출력을하면 콘솔출력에만 성적이 가능하다.
콘솔이 아닌 것 UI와 데이터서비스 분리하게끔 해서 다른 UI(윈도,웹,모바일) 에도 쓸 수있다.
그렇기 때문에 분리가 필요하고, 분리 후 결합해야함
1) 결합하기
<ExamConsole>
package ex6.has_A;
public class ExamConsole {
Exam exam; //이렇게 하면 결합관계가 만들어진다.
//a를 가지는 방법은 두가지
// composiotion has a (실존하는 'a'객체를 가지고(has)있다. 컴포지션으로...) 관계
// 시계는 완성품으로 나온다.(조립하게끔이 아님) 이것이 컴포지션관계
// 다 알아서 가져온다
// 조립하는것은 association 관계 이 경우 부품을 다 알아야한다.
// 내가 결합해야한다.
}
<Exam>
package ex6.has_A;
public class Exam {
private int kor1;
private int eng;
private int math;
}
데이터와 입출력을 분리해서 하자
ExamConsole 클래스에서 Exam클래스를 부품처럼(결합관계) 이용하려면,
Exam의 인스턴스 참조변수(exam)를 선언해주어야한다.
이런 경우 exam은 단순히 참조변수보다는 ExamConsole클래스의 부품으로 볼 수 있다.
즉 원래는 하나의 클래스였으나 분리되면서 하나는 제품, 하나는 부품이 된다. (Dependecny)
2) 결합 후 이용하기 (with setters, getters)
public class ExamConsole {
Exam exam;
public void input() {
//1. 콘솔 성적 입력
// this.exam.eng
// public 을 쓰는 충동을 참자.
// 데이터 속성의 값은 노출해도되나
//데이터 구조는 노출하면 안된다.
//이경우 세팅해주는 함수를 만들자
.
.
.
}
두개의 클래스를 결합하는데 Exam의 exam 인스턴스(부품)은 ExamConsole 클래스에 결합되는데,
이 경우 this.exam.eng로 접근이 가능하다 (제품의 실체와 부품의 실체)
이 경우 this를 쓰는데, 실체화됐다고 직접보기도 어려울 수도있다
그러나 부품이 실체화되어야 실체화된 제품에 붙일수 있기 때문에다
다만 이렇게 접근이 가능하다고 하더라도 exam의 구조를 흔들면안된다.
그렇기 때문에 Exam 의 멤버변수들은 접근제어자로 제한하고 메소드로 접근해야한다.
(3) setter getter (Auto)
멤버변수들은 private 이기 때문에 직접 접근하지못한다.
그렇기 때문에 아래와 같은 메소드를 이용해서 접근하는데, public으로 접근지정자를 정해준다.
public void input() {
exam.setKor1(kor1);
//이런경우 세터함수를 쓴다.
//흔하게 이용하기 때문에
exam.setEng(eng);
exam.setMath(math);
}
public void printExam(char ch, int length) {
int total = exam.total();
double avg = exam.avg();
System.out.printf("점수는 ");
System.out.print(" 국어: " + exam.getKor1());
System.out.print(" /영어: " + exam.getEng());
System.out.print(" /수학: " + exam.getMath());
System.out.print(" /총점: " + total);
System.out.printf(" /평균: %.2f " , avg);
System.out.println();
for(int i = 0 ; i< length ; i++)
System.out.printf("%c", ch);
}
이런방식으로 결합관계있는 Exam 클래스의 setors, getors 를 접근한다.
public void setKor1(int kor1) {
this.kor1 = kor1;
}
public void setEng(int eng){
this.eng = eng;
};
public void setMath(int math){
this.math = math;
}
public int getKor1() {
// TODO Auto-generated method stub
return math;
}
public int getEng() {
// TODO Auto-generated method stub
return math;
}
public int getMath() {
// TODO Auto-generated method stub
return math;
}
이경우 setors와 getors는 IDE(이클립스)를 이용해서 자동생성도 가능하다.
(4) has a 상속 : A가 B의 인스턴스를 가지고있다.
이런경우 has a 상속이라고 볼 수있다.
이를 풀어서 말하면은 상위 클래스가 실존하는 객체(a)를 가지고(has)있다.
크게 종류는 세가지이다.
association, aggregation, composition 이다.
1) composition (조합) - 생명주기 일치
의 경우 composition has a 라고도 한다.
예컨데 시계를 구매하는데 시계는 완제품 그 상태 그 자체로 나오는 것을 말한다.
핵심은 카메라 생성을 스마트폰 안에서 한다는것이다 (new )
그렇게되면 카메라는 생명주기를 스마트폰과 공유한다
2) association (연합) - 생명주기 ......비일치?
이와 상반되는 방식으로 시계를 구매하는데 부품들이 오고 이를 직접결합해야한다.
3) aggregation (집합) - 생명주기 비일치
인스턴스를 외부에서 받아오는것이다
(5) has a 상속과 그것의 구현
1) composition (폰 배터리 일체형 :아이폰4S)
이 경우에는 일체형 방식이다. 인스턴스가 생성될 때 초기화되는 생성자를 이용한다.
방법2번도 가능하다. (JDK에서 도입됨)
//방법 1 : 원래의 방법
public class ExamConsole {
Exam exam;
public ExamConsole() {
exam = new Exam();
}
//방법 2
public class ExamConsole {
Exam exam = new Exam();
}
이러한 방식으로 부품(참조변수)에다가 그 메모리공간을 할당해준다
만약에 이를 이용하지않으면 NullPointException이 발생한다
- 금일 오전에 배열을 선언 한뒤 생성자를 이용해서 메모리공간을 할당해준 방식과 유사
2) association (폰 + 배터리 분리형 : 갤럭시 S2)
이 경우에는 앞서 본거처럼 부품을 직접 들고와야한다.
그렇기 때문에 중간단계클래스(ExamConsole)에서 Exam클래스의 메소드 등을 별도로 선언해주어야한다.
<추가>
이런경우
첫번째. 두 클래스(A,B)에 각자의 객체(a,b)를 만든다
두번째. A에 setB메소드를 만든다.
세번째. 본 메소드안에 B의 멤버변수에 대한 setter등을 넣어준다.
네번째. 본 메소드의 매개변수로 b를 넣어준다.
ex: console.setExam(exam);
이런방식에서 흥미로운점은 함수에서 메소드로 변경된 취지와 부합하지못하게 된다.
<정리>
private로 하고 게터세터 이용해야해
assosi 관계와 compo 관계 다른데
차이점 장단점?
assosi 는 다른녀석 바꿔 끼울수있고
compo 는 바꿀수없다 한번하면 같이 생명을같이함
바꿔끼워야하는 상황 : assosi
현실적으로 바꿀수 있게끔 하는것이 더 많이 이용된다.
1. 보충
(1) association, aggregation, composition 정리
https://forthe1900.tistory.com/30
(2) association에 의한 결합방식 좀 더 알아보기
2. 회고
1) 캡슐화에 대한 필요성과 캡슐화(내부)와 캡슐간의 관계파악이 가능해졌다.
캡슐이라는 것은 하나의 역할을 담은 코드의 구성요소라고하는데, 이러한 캡슐은 깨지지않게끔 하기위해 다양한 방법을 이용했다.
이러한 캡슐의 단위가 만들어지면 캡슐간 엮기 즉 관계를 맺어야한다. 이렇게 관계가 맺어지면 그때부터 응용프로그램이락 마땅히 부를 수 있게 된다.
2)캡슐을 깨지는것을 방지해야하는 다양한 방법과 그 대안이 있다.
접근지정자와 getter, setter이있다
놀라운것은 getter,setter은 IDE에서 자체적으로 생성할수있게끔 해준다
이러한 점을 비추어보면 자바에서는 이렇게 하는것이 너무나도 당연하다는 것이 신기했다.
3) 오버로드와 재귀함수 그리고 생성자
메소드 오버로드를 이용하면은 사용자 입장에서 커스터마이징이가능하고, 설사 코드가 길어진다고 하더라도 재귀함수 기법을 이용해서 코드의 길이를 줄이고, 수정의 범위도 손쉽게 줄일 수 있는것이 신기했다.
생성자도 마찬가지이다.
4) 캡슐 분리
캡슐 분리는 다양한 UI(user interface)에서 이용하게끔 사용자 접촉면과 데이터 면을 분리하는 것이 필요하다.
결국 캡슐관 분리가 이루어지는데, 상술한것 처럼 분리가 되면 결합이 되어야한다.
결합은 다양한방법으로 가능하다는 것을 알게되었다.
5) 상속의 유형
상속의 유형에 대해서 어느정도 이해가 갔다. 그 과정에서 과거에 Star UML이 생각이 났다.
어렴풋 그때당시 handout에서 보았던 다양한 클래스간의 관계 내용이었던 것 같다.
구현도 조합의 방식은 가능한데, 연합방식은 잘 되지않는다.
좀더 공부가 필요하다
<마치며>
오늘 공부가 많이 필요하다.
'배움 __IL > TIL 1기' 카테고리의 다른 글
TIL : 18번째- 221222 [12-4-목] (1) | 2022.12.22 |
---|---|
TIL : 17번째- 221221 [12-3-수] (0) | 2022.12.21 |
TIL : 15번째- 221219 [12-3-월] (1) | 2022.12.19 |
TIL : 14번째- 221216 [12-2-금] (2) | 2022.12.16 |
TIL : 13번째- 221215 [12-2-목] (0) | 2022.12.15 |