2010-05-26 8 views
31

일부 데이터를 목록에 저장하는 개체가 있습니다. 구현은 나중에 변경 될 수 있으며 내부 구현을 최종 사용자에게 공개하고 싶지 않습니다. 그러나 사용자는이 데이터 콜렉션을 수정하고 액세스 할 수 있어야합니다. 현재 다음과 같은 내용이 있습니다.List 또는 Collection을 사용하는 것이 더 좋습니까?

public List<SomeDataType> getData() { 
    return this.data; 
} 

public void setData(List<SomeDataType> data) { 
    this.data = data; 
} 

내부 구현 세부 정보가 유출되었다는 의미입니까? 대신이 작업을 수행해야합니까?

public Collection<SomeDataType> getData() { 
    return this.data; 
} 

public void setData(Collection<SomeDataType> data) { 
    this.data = new ArrayList<SomeDataType>(data); 
} 
+9

명심해야 할 점은 실제 컬렉션이나 목록을 반환하면 항목 삭제 또는 전체 삭제 등 원하는 작업을 다른 사람이 할 수 있다는 것입니다. 변경 불가능한 래퍼 또는 목록 사본을 반환하는 것이 더 나을 것입니다. –

+1

@PaulTomblin은 사실이지만 시스템에 다소 과도한 오버 헤드와 인위적인 오버 헤드가 있습니다. 퍼시스턴스 미들웨어에 의해 관리되는 객체로 작업 할 때 변경 불가능한 래퍼가 적합합니다. – comeGetSome

+0

@comeGetSome, 그래서 "must"라기보다는 "may"라고 말한 것입니다. 그것은 유스 케이스에 달렸을 것이다 - 만약 내가 다른 사람들이 사용할 API를 만들고 있다면 복사본이나 래퍼를 반환 할 것이다. 그것이 나 자신이나 신뢰할 수있는 동료를위한 것이라면 javadocs에 큰 "DO NOT MODIFY THIS VALUE"를 넣고 그대로 두었습니다. –

답변

24

단지 사용자가 데이터에 색인을 생성 할 수있게 하시겠습니까? 그렇다면 List를 사용하십시오. 둘 다 인터페이스이므로 구현 세부 사항이 누출되지는 않습니다. 실제로 필요한 최소한의 기능 만 결정하면됩니다.

0

외부 사용자에게 내 데이터의 내부 표현을 숨기고 싶었지만 XML 또는 JSON을 사용했습니다. 어느 쪽이든, 그들은 꽤 보편적입니다.

+0

은 항상 String 반환 유형을 의미합니까? – erdogany

+0

물론. XML과 JSON은 꽤 보편적 인 것으로 의도되었으며 문자열보다 보편적 인 것은 무엇일까? – Cyberherbalist

+2

글쎄, 만약 내가 애플 리케이션간에 데이터를 전달한다면, 나는 그 종류의 인코딩을 사용할 것이다. 하지만 함수에서 리턴 값에 대해 말하면 XML로 변환하고 문자열로 반환 한 다음 호출자가 XML을 구문 분석해야합니까? 배열을 반환하는 것만 큼 복잡하고 오버 헤드가 많습니다. – Jay

1

예, 인터페이스 계약의 일부가 아닌 경우 첫 번째 대체 방법으로 구현 정보가 누설됩니다. 메서드가 항상 List를 반환합니다. 또한 사용자 코드가 컬렉션 인스턴스를 대체하도록 허용하는 것은 다소 위험합니다. 왜냐하면 전달되는 구현이 예상대로 작동하지 않을 수 있기 때문입니다.

물론 사용자를 얼마나 신뢰하는지는 중요합니다. 파이썬 철학을 취하면 "우리 모두 여기에 성인을 동의하고있다"는 첫 번째 방법은 훌륭합니다. 경험이 부족한 개발자가 라이브러리를 사용한다고 생각하고 "베이비 시팅"할 수있는 모든 작업을 수행하고 잘못된 작업을하지 않도록해야합니다. 컬렉션을 설정하지 않고 반환하지 않는 것이 바람직합니다. 실제 컬렉션. 대신 (얕은) 복사본을 반환하십시오.

+1

java.util.Collections에는 컬렉션을 수정하는 모든 메서드가 대신 오류를 반환하도록 컬렉션을 간단하게 래핑하는 unmodifiableList()와 같은 정적 메서드가 포함되어 있습니다. 래퍼를 인스턴스화하는 것은 일정 시간 작동이기 때문에 얕은 복사본 (심지어 변경 가능한 컬렉션이 필요하면 클라이언트 코드 자체를 만들 수 있습니다.)보다 바람직합니다. –

0

사용자에게 제공하려는 보장에 따라 다릅니다. 데이터가 순차적이어서 요소의 순서가 중요하고 중복을 허용하는 경우 목록을 사용하십시오. 요소의 순서가 중요하지 않고 중복이 허용되거나 허용되지 않을 수있는 경우 컬렉션을 사용하십시오. 기본 컬렉션을 실제로 반환하기 때문에 반환 된 컬렉션이 변형 될 수 있기 때문에 get 및 set 함수를 모두 가질 수는 없으며 get 함수 만 가져야합니다. 또한 set 함수를 제공하면 컬렉션 유형을 사용자가 변경할 수 있지만 특정 유형이 사용자에 의해 제어되기를 원할 수 있습니다.

5

가장 일반적인 유형 인 Collection을 사용하면 더 구체적인 유형 인 List를 사용해야하는 명확한 이유가없는 한 가장 적합합니다. 그러나 당신이 무엇을 하든지, 이것이 공개적으로 사용하기위한 API라면 그것이하는 일을 문서에서 분명하게 밝혀야한다. 컬렉션의 얕은 복사본을 반환하면 그렇게 말합니다.

7

키가 큰 계층 구조에있는 인터페이스 또는 클래스의 구현을 반환하는 경우, 표시되는 반환 형식은 호출자에게 보장 할 수있는 최소한의 기능을 제공하는 가장 높은 수준이어야하며, 발신자가 합리적으로 필요하다는 것. 예를 들어, 실제로 반환하는 것은 ArrayList입니다. ArrayList는 List와 Collection을 구현합니다 (다른 것들 중에서도). 호출자가 get (int x) 함수를 사용해야 할 필요가 있다면 Collection을 반환하지 않습니다. List 또는 ArrayList를 반환해야합니다. Set 이외의 다른 것을 사용하도록 구현을 변경하는 이유가 표시되지 않는 한 올바른 대답은 목록을 반환하는 것입니다. ArrayList에 List에없는 함수가 있는지 확실하지 않지만,있을 경우 동일한 추론이 적용됩니다. 반면에 Collection 대신 List를 반환하면 어느 정도 구현을 잠갔습니다. API를 적게 넣을수록 향후 개선 사항에 대한 제약이 줄어 듭니다.

(실제로, 나는 거의 항상 그러한 상황에서 목록을 반환하고, 나를 태워 적이있다.하지만 아마 정말 컬렉션을 반환해야합니다.) 목록을 통해 목록에 인덱스 할 수있는 능력의

9

독립 .get (int), 사용자 (또는 사용자)는 컬렉션의 요소가 안정적이고 예측 가능한 순서로 이루어지기를 기대합니까? 컬렉션에 같은 항목의 배수가있을 수 있습니까? 이 두 가지 모두 일반적인 컬렉션에 공통적이지 않은 목록에 대한 기대치입니다. 이는 최종 사용자에게 공개 할 추상화를 결정할 때 사용하는 테스트입니다.

14

목록을 반환하는 것은 가장 적합한 인터페이스로 프로그래밍하는 것과 같습니다.

반환 된 컬렉션은 집합, 목록 또는 대기열 일 수 있으므로 컬렉션을 반환하면 사용자에게 모호한 결과가 발생합니다.

관련 문제