Java로 작성된 API에서 내부 클래스를 캡슐화하는 방법은 무엇입니까?


9

라이브러리를 작성해야합니다. 당연히 아주 작은 API (필요한만큼 작은)를 가져야합니다. 라이브러리의 내부는 다소 복잡합니다. 따라서 구조화가 필요합니다.

구조화를 위해 현재 두 가지 방법이 있습니다.

1. 패키지를 사용하십시오.

장점 : 라이브러리를 깔끔하게 구성 할 수 있습니다. 그 자리에있는 모든 것.

단점 : 패키지 테두리를 통한 클래스 사용에는 공개 클래스가 필요하므로 전체 라이브러리의 API가 확장됩니다.

2. 정적 내부 클래스를 모두 하나의 패키지에 사용하십시오.

장점 : 아주 적은 공공 물건 (클래스, 메소드 등) 만 필요합니다.

단점 : 클래스는 클래스를 구성하기 위해 숨겨져 있습니다. 정적 내부 클래스가 너무 많이 사용되는 경우는 거의 없습니다. 개발자는 익숙하지 않아 간과 할 수 있습니다.


잘 구조화 된 라이브러리에서 작은 API를 얻는 더 좋은 방법이 있습니까?

편집 : 언급하는 것을 잊었습니다 .Android 라이브러리 용입니다. 따라서 java9이 없습니다.


내부 클래스가 정적이어야하는 이유는 무엇입니까?
David Arno

내부 클래스가 코드 단위를 더 크게 만들지 않습니까? 내부 클래스가 여러 개인 클래스는 매우 길어질 수 있습니다.
Tulains Córdova

2
@ TulainsCórdova, 좋은 점은 "내부"라는 용어를 "내부"라고 읽습니다. Java는 "package-private"이라고 부릅니다. lib를 작성하는 일반적인 방법은 공개 / 패키지 전용의 다른 모든 클래스와 함께 몇 개의 공개 클래스를 포함하는 하나의 패키지를 갖는 것입니다.
David Arno

안녕하세요 @frmarkus. 좀 더 구체적으로 질문 제목을 다시 작성하고 "당신이 무엇을 묻고 있는지 불분명 한"투표를 피하려고했습니다. 실제 질문이 잘못되었다고 생각되면 자유롭게 다시 편집하십시오.
Andres F.

1
@ TulainsCórdova : 예, 코드 단위가 커집니다 (파일 당 3k 줄의 코드). 이것이 이런 구조화 방식의 또 다른 중요한 문제입니다.
Markus Frauenfelder

답변:


1

2로 무엇을하고 있는지 알 수 있습니다. 클래스를 패키지로 사용하고 패키지로 패키지로 사용하므로 패키지 내에서 자신을 격리 할 수는 있지만 클래스를 사용하여 패키지 내에서 구성 할 수 있습니다.

매우 영리합니다. 영리한 것을 조심하십시오.

이렇게하면 동일한 소스 파일에서 여러 클래스를 멈출 수 있으며 (원하는 경우) 경로에 대문자가 추가됩니다.

또한 리플렉션을 사용하여 외부에서 침입하는 경우가 아니면 패키지 내에 테스트 코드를 작성해야합니다.

그 외에는 이것이 작동합니다. 이상하게 보일 것입니다.

사람들은 Hashtable의 EntrySet 과 같이 사용되는 내부 클래스에 더 익숙합니다 . 그것은 비공개이므로 만들 수는 없지만 공용 인터페이스를 구현하므로 인터페이스를 통해 대화하고 무언가를 얻을 수 있습니다.

그러나 인터페이스를 통해서도 대화하고 싶지 않은 클래스를 설명하고 있습니다. 그래서 나를위한 인터페이스가 없습니다. 이것은 (당신이 나에게 소스를 제공하지 않는 한)보고 혼란 스러울 것이 없다는 것을 의미합니다.

내가 예상하는 가장 큰 문제는 API를 유지 관리하는 혼란스러운 초보자입니다. 당신은 그들에게 문서와 의견을 던질 수 있지만 어느 쪽이든 읽거나 믿지 않을 때는 대체되지 않습니다.

언어 부족을 보완하는 또 다른 패턴을 만들었습니다. Java에는 패키지 그룹에 대한 액세스 권한을 부여하는 액세스 수정자가 없습니다. "모듈"액세스 수정자가 제안되었다고 들었지만 그 징후는 보이지 않습니다.

상속을 통해 몰래 들어가는 것을 신경 쓰지 않으면 기본 액세스 수정 자 (수정 자 없음)가 여기에서 사용됩니다.이 경우 보호됩니다.

Modifier        Class     Package   Subclass  World
public          Y         Y         Y         Y
protected       Y         Y         Y         N
no modifier     Y         Y         N         N
private         Y         N         N         N 

실제로 원하는 것은 모듈 액세스입니다. 그렇게하면 테스트를 한 패키지에 보관하고 다른 패키지에 코드를 보관할 수 있습니다. 슬프게도 우리는 Java로 가지고 있지 않습니다.

대부분의 사람들은 1을하고 API를 확장합니다. 인터페이스를 올바르게 사용하면 구현에 대한 부담이 줄어 듭니다.

1로 원하는 것을 해킹하는 것은 훨씬 더 나쁘다. 호출 스택을 들여다보고 전화를 한 것이 마음에 들지 않는 패키지에서 나올 때마다 예외를 던집니다. 아이유


3

반드시 코드를 패키지로 분리하십시오. 유지 보수성을 향상시키기 위해 먼 길을 갈 것입니다.

최종 사용자가하지 말아야 할 것들에 액세스하지 못하게하려면 API를 인터페이스와 구현으로 분리해야합니다.

Java 인터페이스와 관련하여 전체 API를 정의하고 구현 객체를 생성하기 위해 몇 가지 팩토리 클래스를 제공함으로써 말 그대로 그렇게 할 수 있습니다. 이것이 JDBC가하는 일입니다.

또는 internal패키지 를 작성 하고 구현에 따라 패키지를 문서화하고 경고 나 이전 버전과의 호환성없이 변경 될 수있는 규칙을 통해 규칙을 통해이를 수행 할 수 있습니다 .


1
불행히도, 이것은 완전히 끝이 없습니다. 이것은 많은 공공 수업으로 떠납니다. 힌트가있을 수 있습니다 (공장 또는 '내부'). 그러나 나는 그들에게 ( 모든 공공 수업에) 추가 도구를 적용해야하지만 이것은 좋지 않습니다.
Markus Frauenfelder

@frmarkus-나는 (1) 너무 많은 액세스 제어를 기대하고 있거나 (2) 한 패키지의 클래스가 다른 패키지의 클래스에 의존 할 필요가 없도록 패키지 구조를 다시 생각해야한다고 생각합니다. 패키지 (모든 것을 정적 중첩 클래스로 유지할 수 있다면 어렵지 않아야 함).
kdgregory
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.