제네릭(Generic)적용
: Object 타입처럼 다양한 타입에 대응할 수 있다.
: 특정 타입으로 제한할 수 있다.
=> 마치 각 타입 별로 클래스를 정의한 듯한 효과를 볼 수 있다.
1. 다형적 변수 적용 전
BoardHandler <- BoardList(<-Board), MemberHander <- MemberList(<-Member) 각 객체의 배열을 저장
단점: 각 타입별로 List 클래스를 만들어야 한다. 타입은 다른데 List의 기능은 같음. => 코드 중복
2. 다형적 변수 적용
Object [ ]<-ArrayList(<-MemberHandler & BoardHandler)
Object: Member, Board 담을 수 있음, 다양한 타입의 인스턴스(주소)를 저장할 수 있다. => 타입별로 List를 만들 필요가 없다.
단점:
인스턴스를 꺼낼 때마다 형변환을 해야해서 귀찮음
특정 타입만 다루도록 제한할 수 없음 => 타입 안정성을 해친다.
3. Generic => Type parameter
클래스가 다룰 타입정보를 넘긴다.
class ArrayList<What> {
public void add(What obj) { ... }
public what get(int index) { ... }
}
What : 타입 이름을 받을 변수 = Type parameter
What: 타입을 받는 변수 . List를 코드에서 사용하는 시점에 타입을 받겠다 .
Board를 받으면 다 Board, Member면 Member
일반 변수가 아닌 타입을 받는 거니까 보통 이름을 알파벳 하나로 "T"로 적음
일반 변수로 오해할 수 있기 때문에 what 대신 What이라고 적기.
일반 클래스처럼 오해할 수 있기 때문에 What이라고 적기보다 알파벳 하나로 적기.
일반 변수가 아닌 타입을 받는 거니까 보통 이름을 알파벳 하나로 "T"로 적음
<많이 쓰는 거 >
E Element / 어떤 목록(항목)에서 하나, 리스트에 저장할 항목의 타
K Key / hash map에서 key 객체를 가르킬때
N Number / 숫자를 가르킬때
T type
V value
S U V = 2nd, 3rd, 4th types / 여러개를 받아야할 상황이면 덧붙이기.
하지만 E의 타입이 지정되지 않은 상태에서 배열을 생성할 수 없음. 컴파일러 문제! (그냥 그런갑다,,)
제네릭을 사용할 땐 배열 생성하는 곳에선 쓸 수 없다.
경고 띄우지마 supress = >경고 뜨는건 다 없애기
(형변환)
(E)
제네릭에서 타입을 안 알려주면 Object가 기본임 .
<T> : 타입 파라미터. 클래스 아니고 파라미터라는 걸 나타내는 것. // toArray를 호출할 때 넘어오는 파라미터를 따라 타입이 결정됨 / / T 라는 타입을 메서드를 호출하는 시점에 넘어오는 타입을 따라 배열을 리턴하겠다
객체를 만들어주는 메서드는 팩토리 메서드임.
객체 생성과정이 복잡할 때 팩토리 메서드를 만들어서 사용함.
내가 지정한 타입
Iterator 패턴을 활용하여 데이터 조회기능을 객체로 추출하기 (캡슐화하기)
1. 목록의 값을 조회하기
ArrayList | get(index)로 값 꺼내기 /리스트로 | 데이터 저장 방식에 따라 데이터를 조회하는 방법이 다름. | => | 데이터 저장 방식에 상관없이 일관된(통일된) 방식으로 데이터를 조회하기 | |
LinkedList | get(index)로 값 꺼내기 /리스트로 | ||||
stack | pop()으로 값 꺼내기 /LIFO | ||||
Queue | poll()로 값 꺼내기 /FIFO |
통일된 방식 hasNext() / next() |
Iterator 데이터를 꺼내주는 일을 하는 객체 |
get() | ArrayList |
get() | LinkedList | ||
pop() | stack | ||
pull() | Queue |
*Iterator mechanism(구동원리)
*client : 1. network 분야: 서버에 요청하는 역할을 수행하는 S/W 2. oop 분야: 다른 객체를 사용하는 객체(class)
2. 인터페이스에 따라 만든 클래스의 인스턴스를 리턴한다는 뜻
*Iterator 패턴 구현
1. 구현 1
객체지향 프로그램 유지 보수를 위해 쌍방 참조는 안 됨 !
2. 구현 2- static nested class (중첩클래스 사용)
3. 구현 3 - non static nested class
4. 로컬 중첩클래스
특정 메서드 안에서만 사용할 클래스라면 그 메서드 안에 정의하는게 유지보수에 좋다.
인스턴스 메서드 안에서 로컬 클래스 추가하기.
눈에는 안 보이지만 바깥 클래스의 인스턴스 주소를 받는 생성자와 그 주소를 저장할 인스턴스 변수가 자동으로 추가된다.
5. anonymous class익명 중첩클래스
자체적으로 바깥 파라미터를 받을 생성자가 자동으로 생김
new Iterator<> () { ... }
인스턴스 생성
인터페이스 명 또는 클래스 명
수퍼클래스 생성과 호출을 위한 파라미터 값
익명클래스 바디(몸체)
@Override
public Iterator<E> iterator() {
// 방법1: top level class
// return new ListIterator<>(this);
// 방법2: static nested class
// return new ListIterator2<>(this);
// 방법3: non-static nested class
// return this.new ListIterator3<>();
// 위 문장은 컴파일러가 return new ListIterator3<>(this) 문장으로 변경한다.
// 방법4: local class
// class ListIterator4<T> implements Iterator<T> {
// // 여기 눈에는 안보이지만, 바깥 클래스의 인스턴스 주소를 받는 생성자와
// // 그 주소를 저장할 인스턴스 필드가 자동으로 추가된다.
// int cursor;
// @Override
// public boolean hasNext() {
// return cursor < AbstractList.this.size();
// }
//
// @SuppressWarnings("unchecked")
// @Override
// public T next() {
// return (T) AbstractList.this.get(cursor++);
// }
// }
// return new ListIterator4<>();
// 위 문장은 컴파일러가 return ListIterator4<>(this) 문장으로 변경한다.
// 방법5: anonymous class
return new Iterator<E>() {
// 여기 눈에는 안보이지만, 컴파일러가 바깥 클래스의 인스턴스 주소를 받을 생성자와 필드를 자동으로 추가한다.
int cursor;
@Override
public boolean hasNext() {
return cursor < AbstractList.this.size();
}
@Override
public E next() {
return AbstractList.this.get(cursor++);
}
};
}
// static nested class
static class ListIterator2<T> implements Iterator<T> {
List<T> list;
int cursor;
public ListIterator2(List<T> list) {
this.list = list;
}
@Override
public boolean hasNext() {
return cursor < list.size();
}
@Override
public T next() {
return list.get(cursor++);
}
}
// non-static nested class = inner class
class ListIterator3<T> implements Iterator<T> {
// 바깥 클래스의 인스턴스 주소를 받아서 보관할 인스턴스 변수가 자동으로 추가된다.
// List<T> list;
int cursor;
// 바깥 클래스의 인스턴스 주소를 받는 생성자가 자동으로 추가된다.
// public ListIterator2(List<T> list) {
// this.list = list;
// }
@Override
public boolean hasNext() {
return cursor < AbstractList.this.size();
}
@SuppressWarnings("unchecked")
@Override
public T next() {
return (T) AbstractList.this.get(cursor++);
}
}
'[네이버클라우드] 클라우드 기반의 개발자 과정 7기 > 웹프로그래밍' 카테고리의 다른 글
[NC7기-44일차(6월27일)] - 웹프로그래밍 25일차 -2 (0) | 2023.06.27 |
---|---|
[NC7기-44일차(6월27일)] - 웹프로그래밍 25일차 (0) | 2023.06.27 |
[NC7기-42일차(6월23일)] - 웹프로그래밍 23일차 -2 (0) | 2023.06.23 |
[NC7기-42일차(6월23일)] - 웹프로그래밍 23일차 (0) | 2023.06.23 |
[NC7기-41일차(6월22일)] - 웹프로그래밍 22일차 (0) | 2023.06.22 |