2010-07-28 2 views
8

다형성을 연구하고 아래와 같이 동적 메서드 바인딩을 수행 할 수 있음을 이해합니다.Collection 인터페이스를 사용하여 ArrayList 객체를 만드는 다형성의 이점은 무엇입니까?

클래스 Animal이 추상 클래스라고 가정합니다.

public class AnimalReference 
{ 
    public static void main(String args[]) 
    Animal ref     // set up var for an Animal 
    Cow aCow = new Cow("Bossy"); // makes specific objects 
    Dog aDog = new Dog("Rover"); 

    // now reference each as an Animal 
    ref = aCow; ref.speak(); 
    ref = aDog; ref.speak(); 
} 

내가 좋아하는 ArrayList의 인스턴스 생성하는 데 사용 :

ArrayList myList = new ArrayList(); 

을하지만 보통 나는 사람들이 작성하는 것이 생각 :

Collection myList = new ArrayList(); 

그래서 내 혼란이 컬렉션으로 선언의 이익은 무엇인가 ? 또한 "myList"앞에 "Collection"(추상 클래스가 아닌 인터페이스)을 가질 수 있는지도 몰랐습니다.

그것은 좋은 방법이 아닌 이유는 대답 :

ArrayList myList = new ArrayList(); 

내가 Collection 인터페이스와 ArrayList를 자바 문서뿐만 아니라 온라인 자습서를 읽을 수는 있지만 아직 정말 명확하지 .. 사람이 나에게 몇 가지 설명을 줄 수 있을까요?

답변

10

myListArrayList으로 지정하면 구체적인 유형이 수정됩니다.그것을 사용하는 사람은 누구나이 구체적인 유형에 의존 할 것이고 ArrayList과 관련된 메소드를 (우연히) 부르는 것이 쉽습니다. 나중에 언젠가는 예를 들어로 변경하기로 결정했습니다. LinkedList 또는 CopyOnWriteArrayList 인 경우 클라이언트 코드를 다시 컴파일해야하고 경우에 따라 변경해야합니다. 인터페이스를 프로그래밍하면 이러한 위험이 제거됩니다.

CollectionArrayList 사이에는 또 다른 추상화 수준 인 List 인터페이스가 있습니다. 일반적으로 목록의 사용 패턴은 맵, 세트 또는 대기열의 사용 패턴과 매우 다릅니다. 따라서 직업에 필요한 수집 유형은 일반적으로 일찍 결정되며 변경되지 않습니다. 변수를 List으로 선언하면이 결정이 명확 해지고 고객에게이 컬렉션이 따르는 계약에 대한 유용한 정보를 제공합니다. Collection OTOH는 일반적으로 요소를 반복하는 것 이상으로 유용하지 않습니다.

0

CollectionArrayList의 수퍼 유형입니다. Collection이 제공하는 기능 만 필요한 경우에는 선언에 필요한 기능을 명시 적으로 표시 했으므로 좋은 방법입니다. 초기화에있는 ArrayList을 선택하는 것은 관계가 없습니다 (좋은 기본 선택 임에도 불구하고). Collection이라는 신고는 귀하와 향후 계약자에게 귀하가 관심을 갖는 계약을 정확히 알려줍니다.

+0

왜 이것이 우수 사례인지 자세히 설명해주십시오. –

+0

@Jacob Tomaw _declaration_ 변수에 필요한 기능을 명시 적으로 표시하기 때문에 좋은 방법입니다. _initialization_에서'ArrayList'를 선택한다는 것은 무의미한 것입니다 (좋은 기본 선택 임에도 불구하고). 그것이 '콜렉션'이라는 선언은 당신과 미래의 코더에게 당신이 관심을 갖는 계약을 정확히 알려줍니다. –

+0

당신은 모든 사람들이 그것이 좋은 습관이라고 알고 있다고 가정하지 않고 대답에 그것을 포함시킴으로써 답을 극적으로 향상시킬 수 있습니다. 나는이 질문을 읽는 대부분의 사람들이 당신이나 내가 가진 경험이 없을 것이라고 생각합니다. –

0

myList을 콜렉션으로 선언하고 사용하면 구현 선택을 숨길 수 있습니다 (이 경우 ArrayList로 나타남). 일반적으로 이것은 코드 조각에 의존하는 모든 것들은 특히 ArrayList가 아닌 Collection으로 동작하는 myList에만 의존한다는 것을 의미합니다. 그런 식으로 나중에 다른 것으로 표현하기로 결정했다면 (Set? A Linked List?) 어떤 이유로 든 다른 것을 깨뜨리지 않습니다.

+1

'Map'은'Collection'을 확장/구현하지 않습니다. – Powerlord

+0

좋은 지적. 그러나 요점은 여전히 ​​유효하길 바랍니다 :) – Gian

+1

답변을 편집 할 수 있다는 것을 알고 계십니까? – DJClayworth

3

ArrayList을 선언하는 경우 왼쪽의 유형으로 ArrayList을 사용하지 않습니다. 대신 인터페이스에 프로그래밍하십시오 (List 또는 Collection).

메서드를 Collection으로 선언하면 List 또는 Set을 전달할 수 있습니다.

부수적으로, Generics을 사용하는 것이 좋습니다.

편집 : Generics는 또한 일부 Gotchas를 소개합니다.

List<Animal>ArrayList<Animal> 저장하지만, 하지ArrayList<Cat> 수 있습니다. ArrayList<Cat>을 저장하려면 List<? extends Animal>이 필요합니다.

4

List<Something> myList = new ArrayList<Something>();을 쓰는 것보다 일반적으로 Collection을 사용하는 것이 더 일반적입니다. 일반적으로 목록의 일부 측면이 중요합니다. 집합 또는 목록 (또는 무엇이든) 이건간에 중복 요소를 수락하는 것과 관련하여 애매 모호한 것은 Collection입니다.

이외에도 주된 목적은 추상화 또는 구현 독립성입니다. 내가 가지고있는 목록이 ArrayList 또는 Vector 일 경우 실제로 관심이 있습니까? 아마도 대부분의 시간은 아닙니다. 내 코드는 객체를 필요로하는 가장 일반적인 인터페이스를 사용하는 경우보다 융통성이 있습니다.

쉬운 예입니다, 당신은 모든 ArrayList S를 사용하여 프로그램을 작성한다고 가정하고, 스레드 안전을 위해 당신이 Vecto RS에 모든 ArrayList의를 변경할 수 있도록 다음, 나중에는 여러 사용자를 지원해야합니다. Type ArrayList에 대한 참조를 전달하고 있다면 모든 곳에서 모든 용도를 변경해야합니다. 유형 List에 대한 참조를 전달한 적이 있다면 유형을 생성 한 위치 만 변경하면됩니다.

또한 구현 클래스는 가져 오거나 사용할 수있는 것이 아니기도합니다. 예를 들어 hibernate와 같은 지속성 공급자를 사용할 때 Set 인터페이스를 구현하는 실제 클래스는 프레임 워크 고유의 고도로 특수화 된 사용자 정의 구현 일 수 있으며 객체 생성 방법에 따라 보통 HashSet 일 수 있습니다. 차이점에 대해 신경 쓰지 않고 단지 Set입니다.

1

먼저 상속과 인터페이스간에 중요한 차이가 있습니다. 짧은 여행 역사 : 평범한 오래된 C++에서는 여러 클래스에서 상속받을 수 있습니다. "변속기"클래스가 "Vehicle"및 "Human"에서 상속하여 "MoveForward"라는 메서드를 구현하는 경우이 작업은 부정적인 결과를 낳습니다. "Transformer"클래스에서이 메서드를 호출하면 인스턴스가 사용하는 dshoud 함수는 무엇입니까? "인간"또는 "차량"구현? 이 문제를 해결하기 위해 인터페이스는 java, C#, ...에 의해 소개됩니다. 인터페이스는 클래스와 다른 것 사이의 계약입니다. 기능에 대한 약속을하지만 계약이 클래스에 대한 로직을 구현하지 않습니다 (Transformer.MoveForward "문제를 방지하기 위해).

다형성이란 일반적으로 다른 방식으로 나타날 수있는 것을 의미합니다."변압기 "는 "Vehicle"과 "Human". 언어에 따라 (C# 사용) 수행하려는 계약에 따라 "MoveForward"에 대해 다른 동작을 구현할 수 있습니다.

구체적인 구현 모자 대신 인터페이스 사용 먼저 코드를 변경하지 않고 구현을 전환 할 수 있습니다 (Google lookup에 대한 Dependency Injection). 두 번째로 테스트 프레임 워크 및 조롱 프레임 워크로 코드를 더 쉽게 테스트 할 수 있습니다.셋째, 가장 일반적인 인터페이스 데이터 교환을 사용하는 것이 좋습니다 (값을 중재하기를 원하는 경우 목록의 열거 자 instad).

희망 사항은 인터페이스의 장점을 이해하는 데 도움이되기를 바랍니다.

1

로컬 변수 선언 (ArrayList 예와 같이)에서 사용하는 유형은 일반적으로 그다지 중요하지 않습니다. 보장해야 할 것은 myList 유형 (myList의 왼쪽에있는 단어)이 myList를 취하는 모든 메소드 매개 변수의 유형보다 더 구체적 이도록 입니다.

고려 :

ArrayList words = new ArrayList(); 
sort(words); 
removeNames(words); 

public void sort(Collection c) ... blah blah blah 

public void removeNames(List words) ... 

난 그냥 목록으로 '말'의 유형을 대체 할 수 있었다. 은 내 프로그램의 가독성 또는 작동에 어떤 차이가 없습니다. '단어'를 Object로 정의 할 수 없습니다. 너무 일반적입니다. 공용 방법을 정의 할 때 내가 정의한 경우 관련 메모에

은, 당신 . 호출자가에 전달할 수있는이에 직접적인 영향을 때문에, 메소드의 매개 변수의 유형에 대해 충분히 고려한다 일종의 다르게 :

ArrayList words = new ArrayList(); 

// this line will cause a compilation error. 
sort(words); 

public void sort(LinkedList c) ... blah blah blah 

종류의 정의는 지금 매우 제한적입니다. 첫 번째 예제에서 정렬 메서드는 컬렉션을 구현하는 한 모든 개체를 매개 변수로 허용합니다. 두 번째 예제에서는 정렬은 LinkedList 만 허용하고 다른 것은 허용하지 않습니다 (ArrayLists, HashSets, TreeSets 등). 정렬 방법이 일 수있는 시나리오는 이제 매우 제한적입니다. 이것은 좋은 이유 일 수 있습니다. 정렬의 구현은 LinkedList 데이터 구조의 기능에 의존 할 수 있습니다. 코드를 사용하는 사람들이 LinkedLists 이외의 다른 알고리즘에서 작동하는 정렬 알고리즘을 원할 경우이 방법으로 정렬을 정의하는 것은 안 좋은 일입니다.

자바 라이브러리 작성의 주요 기술 중 하나는 메소드 매개 변수 을 결정하는 것입니다. 얼마나 일반적으로되고 싶니?

1

글쎄, arraylist 동적 크기가 있습니다. 콜렉션에는 컴파일 시간을 점검 할 필요가 없으므로 유형을 캐스트해야합니다. 컬렉션에는 참조별로 개체 만 들어 있습니다. 컬렉션을 "가방"이라고 생각할 수 있습니다. 그리고 조작은 전체 대상에 대해 수행 될 수 있습니다. 또한 컬렉션에 대한 검색 시간이 ArrayList와 비교하여 짧지 만 긍정적이지는 않습니다. ArrayLists는 더 많은 기능과 메서드를 호출 할 수 있습니다.

관련 문제