Whiteship's Note


Generic과 다형성 2탄

Java : 2007. 1. 5. 15:13


앞서 살펴본 Generic과 다형성에서 보았던 답답함을 해결하는 간단한 방법은 와일드 카드를 사용하는 것입니다. feedAnimals메소드를 다음과 같이 수정합니다.

private void feedAnimals(List<? extends Animal> animals) {

             for(Animal animal : animals){

                    animal.eat();

             }

       }


위 코드는 아래와 같이 써도 똑같은 의미 입니다. 다른 의미 입니다. 위에 것은 상위 제한이 Animal인 어떠한 타입이든(Dog든 Cat이든 Animal을 상속 받았다면..) 올 수 있는데 아래 것은 상위 타입이 Animal인 어떤 타입 하나(Dog면 Dog, Cat이면 Cat)만 올 수 있기 때문에 콜렉션에 타입 제약을 가할 수 있기 때문에 추가가 됩니다. T 타입으로 추가를 해야겠죠.

private <T extends Animal> void feedAnimals(List<T> animals) {

             for(Animal animal : animals){

                    animal.eat();

             }

       }


그럼 이런 상황에서 Dog 리스트에 Cat 객체를 넣으려는 건 어떻게 방지가 될까가 궁금합니다. 컴파일러는 위와 같이 ? 나 T 같은 와일드 카드[각주:1]가 사용되면 컴파일러는 콜렉션에 추가하는 작업을 허용하지 않습니다.

따라서 다음고 같은 코드를 컴파일 에러를 발생시킵니다.

private <T extends Animal> void feedAnimals(List<T> animals) {

             for(Animal animal : animals){

                    animal.eat();

             }

             animals.add(new Dog());   //에러

             animals.add(new Cat());   //에러

             animals.add(new Animal());  //에러

       }


하지만 다음과 같이 추가하는 작업을 할 수 있습니다.
    private <T extends Animal> void feedAnimals(List<T> animals, T a) {
        for(Animal animal : animals){
            animal.eat();
        }
//        animals.add(new Dog());
//        animals.add(new Cat());
//        animals.add(new Animal());
        animals.add(a);
    }
이게 되는 이유는 T라는 타입 하나로 Collection안에 들어가는 요소들의 타입이 제한 할 수 있기 때문입니다.

또 하나 여기서 사용된 extends의 의미는 class head부분에서 사용되는 extends보다 포괄적인 의미를 나타냅니다. extends와 implements를 포함합니다.


참조 : Head First Java

좀더 자세한 내용은 Generics를 참조 하세요.



  1. Java 에서 identifier가 될 수 있는 어떤 문자도 상관이 없습니다. [본문으로]

'Java' 카테고리의 다른 글

제8회 한국 자바 개발자 컨퍼런스  (2) 2007.01.25
GC관련 아티클  (0) 2007.01.19
Generics 번외 - 겉모습만 보곤 알 수 없슴.  (2) 2007.01.17
Generics  (2) 2007.01.17
Eclipse 단축키 모음  (6) 2007.01.11
Generic과 다형성 2탄  (4) 2007.01.05
Generic과 다형성  (0) 2007.01.05
자바 검은 띠에 도전해 보시길~  (2) 2006.12.31
Hiding Method  (0) 2006.12.31
Overriding - covariant return type  (6) 2006.12.31
LinkedList vs ArrayList  (6) 2006.12.22
top

  1. zerry82 2007.01.05 15:32 PERM. MOD/DEL REPLY

    오 몰랐던 부분이네요.. 이런 사실이

    !!!

  2. Favicon of http://mixed.tistory.com BlogIcon 용우 2007.01.05 15:50 PERM. MOD/DEL REPLY

    기선님 위에 코드부분은 수동으로 이렇게 치신건가요?
    아니면 플러그인이 있는건가요?

    Favicon of https://zerry82.tistory.com BlogIcon 동자~ 2007.01.05 16:12 신고 PERM MOD/DEL

    http://realstudy.oranc.co.kr/tt/61

    이곳으로 가보시면 설명되어있습니다!

    혹시 더 나은 방법이 있다면!! 리플을 !!

    Favicon of http://whiteship.tistory.com/ BlogIcon 기선 2007.01.05 16:57 PERM MOD/DEL

    zerry82님이 잘 설명해 놨네요.
    이클립스에서 워드에 복사해 놓고 다시 그걸 복사해서 붙여 넣으시면 됩니다.

    손은 좀 가도 코드 보기가 훨씬 좋네요.

Write a comment.


Generic과 다형성

Java : 2007. 1. 5. 14:27


사용자 삽입 이미지
위와 같은 계층 구조를 가진 클래스를 사용하는 콜렉션을 다음과 같이 코딩을 합니다.

public class AnimalCollection {

       @Test

       public void feedingAnimalList(){

             List<Animal> animals = new ArrayList<Animal>();

             animals.add(new Animal());

             animals.add(new Dog());

             animals.add(new Cat());

             feedAnimals(animals);

       }

 

       private void feedAnimals(List<Animal> animals) {

             for(Animal animal : animals){

                    animal.eat();

             }

       }

}


결과를 확인하면 다음과 같이 원하는 대로 돌아간 것을 확인할 수 있습니다.
동물이 먹습니다.
강아지가 먹습니다.
고양이가 먹습니다.

다형성을 이용하기 위해서 Dog List를 만들고 이 리스트도 밥을 먹이기 위해서 feedAnimals메소드를 사용해 봅시다.

       @Test

       public void feedingDogList(){

             List<Dog> dogs = new ArrayList<Dog>();

             dogs.add(new Dog());

             dogs.add(new Dog());

             dogs.add(new Dog());

             feedAnimals(dogs);

       }

       private void feedAnimals(List<Animal> animals) {

             for(Animal animal : animals){

                    animal.eat();

             }

       }

위와 같이 코딩을 하면 컴파일에러가 발생하는 것을 알 수 있습니다.

즉 List<Animal> animals 매개변수를 가진 feedAnimals메소드에 List<Dog> 타입이 들어갈 수 없다는 것입니다. 들어가지 못하는 이유는 위험하기 때문입니다. 만약 feedAnimals에서 dogs를 받아 들인다고 했을 때 feedAnimals에서 dogs에 Cat 타입의 객체를 넣을 수도 있을 겁니다.

       private void feedAnimals(List<Animal> animals) {

             animals.add(new Cat());

       }

위와 같은 일이 아예 벌어지지 않도록 컴파일 에러를 내준다고 합니다.


참조 : Head First Java

'Java' 카테고리의 다른 글

GC관련 아티클  (0) 2007.01.19
Generics 번외 - 겉모습만 보곤 알 수 없슴.  (2) 2007.01.17
Generics  (2) 2007.01.17
Eclipse 단축키 모음  (6) 2007.01.11
Generic과 다형성 2탄  (4) 2007.01.05
Generic과 다형성  (0) 2007.01.05
자바 검은 띠에 도전해 보시길~  (2) 2006.12.31
Hiding Method  (0) 2006.12.31
Overriding - covariant return type  (6) 2006.12.31
LinkedList vs ArrayList  (6) 2006.12.22
Agile Java 소스코드(10장까지..)  (8) 2006.12.21
top

Write a comment.


냄새 나는 Switch 코드와 다형성

Java : 2006. 11. 30. 16:02


원문 : Switch Statement code smell and polymorphism
위 글을 보면서 정리하고 있습니다.

switch-case 문을 사용한 소스코드를 보겠습니다.

위 코드를 보시면 swtich-case 문이 두 개의 메소드에서 중복이 되며 이것은 리팩토링이 필요하다는 것을 뜻합니다.

이 코드는 instanceOf 연산자를 사용해서 간추릴 수는 있지만 여전히 중복이 존재합니다. 이럴 때 다형성을 사용하려면 먼저 AbstractShape 클래스나 Shape라는 인터페이스를 만듭니다. 그리고 이를 구현 하거나 상속 받도록 구성합니다.



출처 : http://photos1.blogger.com/blogger/2606/2479/1600/ClassDiagram1.gif

위 UML 대로 코딩한 소스 코드는 다음과 같습니다.

이제 Client 코드에서는 switch 문이 사라집니다.
public class Client {
  private
Shape shape;
  ...
  public double calculateArea() {
      return
shape.getArea();
  }
  public double calculatePerimeter() {
      return
shape.getPerimeter();
  }
}

Clinet의 코드가 처음 것에 비해 굉장히 단순해 졌으며 유연해 졌습니다. 새로운 도형이 추가 되어도 그 도형이 Shape 인터페이스만 구현했다면 이 코드는 수정될 필요가 없어졌습니다.

책임이라는 관점에서 살펴본다면 처음의 Client 코드는 도형의 세부 길이 까지 너무 많은 걸 알고 었는데 반해 여기서는 도형이 뭘 할 줄 아느냐만 (메소드만) 을 이용하고 있습니다.

인터페이스와, 다형성을 사용한 swich문의 중복과 coupling을 해결한 재밌는 글이였습니다.

'Java' 카테고리의 다른 글

... 가변인수(varargs)  (2) 2006.12.11
for each 구문 사용법  (0) 2006.12.11
JUnit Reloaded  (0) 2006.12.07
I/O Stream 구성  (0) 2006.12.07
Checked Exception VS Unchecked Exception  (0) 2006.12.01
냄새 나는 Switch 코드와 다형성  (3) 2006.11.30
Map 인터페이스 살펴보기  (0) 2006.11.29
Abstract Test  (6) 2006.11.28
상속을 이용한 다형성 vs 인터페이스를 이용한 다형성  (0) 2006.11.24
Throwable 계층구조  (0) 2006.11.21
상속에 대하여...  (6) 2006.11.20
top

  1. Favicon of http://zerry82.tistory.com BlogIcon 현동규 2006.12.01 10:57 PERM. MOD/DEL REPLY

    : http://photos1.blogger.com/blogger/2606/2479/1600/ClassDiagram1.gif

    이거 에러떠여~

    Favicon of http://whiteship.tistory.com/ BlogIcon 기선 2006.12.01 12:24 PERM MOD/DEL

    흠~ 희한하네 난 잘 보이는데; 불여우에서 봐봐
    원문에 있는 그림이라서 출처를 붙일 필요는 없는것 같은데 걍 지울까;;

  2. Favicon of http://zerry82.tistory.com BlogIcon 현동규 2006.12.02 14:04 PERM. MOD/DEL REPLY

    어 보인다 -_-;;

Write a comment.