카테고리 없음

PECS 원칙 이해 참고

코딩연습중 2025. 4. 9. 16:29

List<? extends Animal> list = new ArrayList<Dog>(); 이렇게 했을 때 Dog, Cat, Bird 모두 Animal 타입으로 safely 읽을 수 있다고 했는데 그럼 리스트에서 get 해왔을 때 그거의 타입이 Animal이라는 거야?? 그리고 조금 헷갈리는 게 저게 각각 읽기, 쓰기에 적합하다는 건 알겠어. 근데 저렇게 list의 타입에 와일드카드를 붙이면 특정(쓰기, 읽기 둘 중 하나) 역할밖에 못 하는데 왜 쓰는거야? 어떨 때 써??

 

 

 

너무 좋은 질문이다. 와일드카드(? extends, ? super)는 자바 제네릭의 핵심 컨셉 중 하나고, 이걸 언제 쓰는지를 이해하는 게 정말 중요해.
정리해줄게 👇


✅ 1. List<? extends Animal> list = new ArrayList<Dog>();

➤ 그럼 list에서 get 해온 요소의 타입은?

✅ Animal 타입이다!

왜냐면 **"Dog가 Animal의 하위 타입"**이기 때문에,
list.get(0)의 리턴 타입은 Animal이라고만 보장되고
실제로는 Dog일 수 있지만, 컴파일러는 모른다.

Animal a = list.get(0); // ✅ OK
Dog d = list.get(0);    // ❌ 컴파일 에러 (불확실하니까)

✅ 2. extends, super의 쓰기/읽기 관계

와일드카드 읽기 쓰기

? extends T ✅ 가능 ❌ 불가
? super T ❌ 불가 ✅ 가능

✅ 3. ❓왜 쓰는가?

와일드카드는 불특정한 타입 계층을 안전하게 다룰 때 사용한다.
자주 쓰는 케이스는 아래처럼 API를 설계하거나 라이브러리를 만들 때야.

📌 예시 1: 상위 타입 기준으로 안전하게 읽기 (extends)

public void printAnimalNames(List<? extends Animal> list) {
    for (Animal a : list) {
        System.out.println(a.getName());  // ✅ 읽기 OK
    }
}

여기서 list는 List<Animal>이든 List<Dog>이든 List<Cat>이든 받아서
Animal 타입으로 안전하게 읽을 수 있다.

🔒 하지만 list.add(new Dog()) 는 안 됨.
이유: list가 Dog인지 Cat인지 모르니까 Dog를 넣는 게 위험할 수 있어서.


📌 예시 2: 하위 타입 기준으로 안전하게 쓰기 (super)

public void addDogs(List<? super Dog> list) {
    list.add(new Dog()); // ✅ Dog이거나 그 상위 타입이면 안전하게 쓸 수 있음
}

여기서 list는 List<Dog>, List<Animal>, List<Object> 전부 가능.
Dog를 안전하게 넣을 수 있는 list를 받고 싶은 경우 이렇게 선언한다.

🔒 하지만 Dog d = list.get(0)은 안 됨. Object일 수도 있어서.


✅ 핵심 요약

목적 사용 의미

읽기 전용 (상위 타입 기준) ? extends T T 또는 그 하위 타입이면 OK. 읽기만 가능
쓰기 전용 (하위 타입 기준) ? super T T 또는 그 상위 타입이면 OK. 쓰기만 가능

🔍 그래서 언제 써?

  • 라이브러리나 유틸성 메서드 만들 때
  • 다양한 타입을 포용하면서도 타입 안정성을 유지하고 싶을 때
  • 타입 상한/하한을 두고 타입 범위를 제한할 때

필요하다면 너가 이해한 내용 정리해서 블로그 글처럼 포맷팅해줄 수도 있어! 😎
조금 더 깊게 들어가도 좋고, 실제 코드 예시로 정리해줘도 돼.