teira
43
2010-03-31 21:06:50
11
31831

자바의 다형성? List list = new ArrayList()


안녕하세요 자바를 시작한지 벌써 1년이 다되가지만 부끄러운 질문하나 드립니다. 아무리 책을 찾아보고 인터넷을 찾아보아도 머리속엔 제대로
정리가 되지않아 답답합니다.
1
Collection list = new ArrayList();
Arraylist list = new ArrayList();

2
HashMap map = new HashMap();
Map map = new HashMap();

이렇게 인터페이스 형태를 선언하고 쓰는걸 잘 모르겠습니다.
정확히 말하면 차이점을 모른다는 겁니다.


**

1번에 list. 으로 접근하면 Collection 메서드만 사용할 수 있죠?

앞에 레퍼런스 변수 타입을 Collection말고 ArrayList로 선언 후

(ArrayList

list. 으로 접근하면 Collection을 상속하고있는 ArrayList에 많은

멤버(메서드)를 사용할 수 있을텐데 왜 Collection으로 선언하나요?

어떤 이점이 있고 왜 이렇게 사용하는지 궁금합니다.

**


다형성에 대한 예제도 찾아보았으나  Api기준으로 설명되어있는게없어
이렇게 질문 드립니다. 자세한 답변 부탁드립니다.

1
  • 답변 11

  • teira
    43
    2010-03-31 20:08:27
    Animal 을 인터페이스로 든 예제.
    Parent 를 예로 든 예제 많이 봤습니다. 정중히 사양합니다
    -3
  • melpis
    118
    2010-03-31 21:15:37
    Collection으로 선언하면 인터페이스에 있는 메소드 밖에 못쓰지만

    대신에 나중에 ArrayList가 아닌 Vector나 기타 자료형으로 쉽게 교체가 가능하죠

    같은것을 상속 받았기 때문에 마치 렉서스, 벤츠가 자동차라고 불리우지만

    자동차가 렉서스, 벤츠는 꼭 아니잖아요 ...여기도 같은 원리라고 보시면 편하 실거

    같네요.. ArrayList Vector 둘다 Collection 일종이지만

    Collection은 꼭 ArrayList가 될수 없는거 처럼....

    뭐 어리석은 소견이였습니다....

  • melpis
    118
    2010-03-31 21:17:26
    아 interface에 사전적인 의미로 접점이라는 의미가 있으니까 서로 연결해줄수

    있는 통로 ...라고 생각하시면 더 편하실듯...(어려워지는건가요 ㅠㅠ);
  • teira
    43
    2010-03-31 21:21:30
    ----------------------------------------
    대신에 나중에 ArrayList가 아닌 Vector나 기타 자료형으로 쉽게 교체가 가능하죠
    ----------------------------------------
    이 말슴은 혹시 Collection 을 Implements하고 있는 클래스들간에는
    Casting이 자유롭기 때문이라는 말슴인가요? (Vector,AbstractSet,AbstractCollection 등등등.;..)


  • teira
    43
    2010-03-31 21:26:41
    아 혹시..
    Collection으로 선언해논 객체 list에는
    나중에
    list = new ArrayList();
    list = new Vector();
    list = new AbstractSet();
    등등등으로 자유롭게 변경할 수 있다는 장점이라는 말슴이신지요?
  • melpis
    118
    2010-03-31 22:41:58
    네 그러한 장점이 있죠...

    그래서 spring framework에서 인터페이스를 주로 사용하는 이유가 그이유죠..

    조합을 할수 있다는 장점과 쉽게 언제든지 교체된다 ..

    라는 장점 ...

    저는 아직 프로그래머도 아니라서 많이 어설퍼요^^;;
  • fender
    26k
    2010-04-01 01:07:59
    보통 인터페이스를 설계할 때는 메소드 시그네쳐만 봐도 개발자의 의도가 드러나야 한다고 이야기합니다. 즉, 네이밍, 리턴 타입, 파라메터, 예외 선언 등만 봐도 무슨 의도로 그 메소드를 설계했는지 명확해야한다는 건데요...

    예를들어 List getProducts();라는 메소드가 있다면 이름과 반환값만 봐도Product, 즉 제품에 해당하는 객체의 묶음을 반환한다는 뜻임을 알 수 있습니다.

    이 때, List를 통해 추가로 알 수 있는 건 반환하는 형은 순서가 있는 컬렉션이고 아마도 개발자는 제품을 이름순으로 정렬한다던지 해서 반환하도록 구현하겠죠...

    그럼 만약 해당 메소드가 ArrayList getProducts()라면 어떻게 되나요?

    ArrayList는 배열을 백엔드로한 List의 한 구현체에 불과합니다. 꼭 그 구현을 쓰는 것이 해당 인터페이스 개발자의 의도라고 볼 수 있을까요? 비즈니스적으로 반드시 제품목록을 가져오는데 배열을 백엔드로 하는 구현체에 담아야한다는 요구조건이 있을 가능성은 적습니다.

    또한 반환형을 ArrayList 같은 구현체 대신에 List라는 인터페이스로 정의하면 의도가 명확하게 한정되는 것 이외에 위의 몇몇 분들께서 말씀하신 것처럼 구현 차원에서 좀 더 자유도를 확보할 수 있습니다.

    좀 구체적으로 예를 들어보면 처음엔 내부적으로 ArrayList로 구현했다가 속도가 마음에 들지 않아 commons collections에 있는 FastArrayList로 바꿀 수도 있는 것이죠. 또 하이버네이트 같은 ORM으로 백엔드 구현을 바꾸어서 getProducts().get(1).getCategory() 이런 걸 레이지 로드로 가져올 수도 있고 (이런 게 가능하려면 하이버에니트에선 List의 프록시를 씁니다) 그런 변화들을 인터페이스의 클라이언트 쪽에 영향을 주지 않고 변경할 수 있는 장점이 있습니다.
  • clean00007
    1k
    2010-04-01 04:16:21
    누군가가 만들어놓은걸 사용하는 입장으로 생각하면 편합니다.
    외부 API 를 사용해야 하는데
    void myMethod(List list)
    이런 타입이라면
    일단 그작자가 왜 저렇게 만들었는지는 모르겠더라도
    '당신이 뭐를 던지던 List 를 상속받은거라면 명시한 기능을 수행해 주겠음'
    이라는 뜻이니 사용하는 입장에서는 자유도가 높아지죠.
  • 크르릉
    2k
    2010-04-01 10:53:33
    부모의 모든걸 자식이 물려받아요 ㅋㅋ
    이것만 알면 끝임
  • chela
    3k
    2010-04-06 10:48:23
    단순한 루틴에서는

    HashMap map = new HashMap();

    이와 같이 써도 똑같습니다. 단순히 쓰는 루틴에선 똑같아요.
    꼭 Map map 으로 할 필요 없습니다.

    그런데, 좀 복잡한 루틴이 되면

    Map map;

    과 같이 선언해 두어야 할 경우가 생깁니다.
    가령 이같은 경우에는 map을 구현하되 HashMap 으로 구현할지 HashTable로 쓸 것인가 모를 경우에 저렇게 쓰고요. 즉, Map map 이하의 구문에서 조건에 따라 그게 달라질 경우 저렇게 선언해 놓습니다. 그냥 여기에서의 예일뿐인데 경우에 따라 Thread Safe가 필요하면 HashTable로 선언을, Thread Safe가 필요없다면 성능이 좋은 HashMap 으로 선언하게 되는거죠. 이런식으로 하기 위해 상위 Interface로 선언하는 경우가 있는겁니다.

    웹프로그래밍에선 WAS 컨테이너에서 많은 부분을 자동으로 처리해 주기 때문에 이런 객체지향 적인 구분이 거의 쓰이지 않지만 Java Swing 에서는 이런게 아주 자주 쓰여요.

    가령 Input 이라는 클래스를 구현하는 Radio 박스와, Check 박스가 있다고 할때
    일단 Input 이라고 선언해 두고, 이후 문제 문항에 따라 Radio 로 생성하기도 하고 Check 로 생성하기도 하는거죠. 값을 입력 받아 저장하는건 똑같지만, 도구를 다르게 가져가는 겁니다.
  • free_hewon
    24
    2010-04-11 12:28:44
    1. 인터페이스 List 대신에 구현 클래스 ArrayList의 형타입을 알 수 있다면 더 편리하게 사용할 수 있습니다. (낮게 나는 새가 더 자세히 본다)

    2. 구현 클래스 ArrayList 대신에 인터페이스 List를 사용하면 더 많은 형타입을 받아 들일 수 있습니다. (높게 나는 새가 더 멀리 본다.)

    예를들어, 목록의 모든 원소를 출력하는 메서드 public void printAll(List items)는
    public void printAll(ArrayList items) 보다 더 많은 종류의 형타입을 받아 들일 수 있습니다. (Vector, Set, etc)

    3. 구현 클래스 ArrayList 대신에 인터페이스 Iterable을 받아 들인다면, 클라이언트는
    인수로 받는 객체의 크기가 변하지 않을것이라는 보증을 할 수 있습니다. (Iterable 객체는 객체를 더 넣을 수 없습니다.

    4. 인터페이스 Map을 만족하는 객체라면 굳이 HashMap이 아니여도 Map을 구현하는 클래스를 만들어 사용할 수 있습니다.
    예를들어 서블릿에서 Cookie를 조작하기 위하여 HttpRequest와 HttpResponse클래스에 의존적인 작업을 해야 합니다만, 이들 클래스를 캡슐화 시키는 일반 클래스 CookieMap클래스를 만들 수 있습니다.

    public class CookieMap implements Map {
    private HttpServletRequest req;
    private HttpServletResponse res;

    ...

    public String get(String key) {
    for(Cookie cookie : req.getCookies()) {
    if(cookie.getName().equals(key)) {
    return cookie;
    }
    }
    }

    public void put(String key, String value) {
    response.addCookie(new Cookie(key, value));
    }
    }

    만약 위와 같은 구체화 클래스 CookieMap를 작성하였다고 할 경우에, 이 클래스의 인스턴스를 일반적인 Map객체와 같은 취급을 하는것이 가능합니다. 따라서 다른 클라이언트가 일반적인 Map의 조작을 하고 있다고 하더라도, 실제 클래스에서는 쿠키를 조작하게 되어 실제 구현을 숨기는, 즉 은닉성을 가지게 됩니다.
  • 로그인을 하시면 답변을 등록할 수 있습니다.