인터페이스에서 보호


111

interface정의의 모든 메서드가 암시 적 으로있는 이유는 무엇 public입니까? protected방법을 허용하지 않는 이유는 무엇 입니까?


22
아주 좋은 질문입니다. Java의 거의 모든 다른 것들에 대해 나는 선택에 대한 진정한 이유를 찾았지만 이번에는 찾지 못했습니다. 동일한 패키지 내의 다른 클래스가 해당 메서드를 노출 할 필요없이 구현 개체에서이 메서드를 사용할 수 있도록하는 인터페이스에서 보호 된 메서드를 정의하는 것이 나에게 완벽합니다. 패키지 회원, 나머지 세계에.
Markus A.

4
@MarkusA. 그러나 인터페이스는 양방향으로 작동합니다. 즉, 현재 패키지 외부의 클래스에 의해 구현 될 수도 있습니다 (그런 다음이 패키지 내부의 메서드에 인수로 전달 될 수도 있습니다). 현재 패키지 외부의 클래스가 일부 공용 인터페이스의 "보호 된"메서드를 어떻게 구현할 수 있습니까?
MartinStettner 2013 년

8
@MartinStettner : 그렇지 않습니다. 그게 요점입니다. 패키지에는 인터페이스를 구현하는 관련되지 않은 여러 클래스가있을 수 있으며 해당 인터페이스 유형의 참조를 수신하는 모든 코드가 특정 방식으로 작동 할 것임을 보장합니다. 이러한 보증은 외부 코드가 계약에 반하는 방식으로 작동하면서 인터페이스를 구현한다고 주장하는 것을 방지 할 수 있다면 훨씬 더 강력해질 수 있습니다.
supercat 2013 년

1
@MarkusA. 당신은 좋은 지적을했다. 당신은 자바 9의 모듈 시스템으로
Nir Alfasi

1
인터페이스에 protectedmethod 가 있으면 모든 구현 클래스가 인터페이스의 하위 유형으로 표시됩니다. 이러한 모든 클래스는 보호 된 메서드에 액세스 할 수 있습니다. 그것은 만든다 나던 protected쓸모없는 방법에 키워드? 메소드 에이 인터페이스 보호 키워드 를 구현 하는 사람 을 제한 하는 방법이없는 한 쓸모가 없습니다. 틀 렸으면 말해줘!
amarnath harish

답변:


67

인터페이스는 "클래스 외부에서 볼 수있는 것"을 의미하기 때문입니다. 비공개 메서드를 추가하는 것은 의미가 없습니다.


16
그러나 인터페이스와 동일한 패키지의 멤버 만 "클래스 외부에서 볼 수있는"함수가없는 이유는 무엇입니까? 나는 이것을 원했던 몇 가지 사용 사례가 있습니다.
Markus A.

5
@MarkusA. 나는 이것이 늦었다는 것을 알고 있지만, 당신은 완전히 abstract class, 즉 모든 interface것을 만들고 원하는 액세스를 지정할 수 있습니다. 이것은 interfaceJava에서 얻는 여러 구현의 이점을 잃지 만 다른 패키지의 제한을 준수하는 계약을 정직하게 설정하는 것은 테스트 할 수없고 혼란 스러울 것입니다. 실제로 해당 패키지 외부에서 자체 구현 방법에 액세스 할 수 없기 때문입니다. .
pickypg 2013-04-18

10
@pickypg 그러나 인터페이스를 구현할 클래스가 이미 다른 클래스를 확장 한 경우 다른 클래스를 확장하도록 만들 수 없습니다. 패키지 내에서만 사용되는 인터페이스에 대해서는 혼동되지 않습니다.
Flamma 2014 년

24
@Raveline, -1, "인터페이스가 클래스 외부에서 볼 수있는 것을 의미하는 이유는 무엇입니까?"라는 질문을 던집니다. Java 8은 이미 인터페이스에서 메서드 본문을 허용하는데 보호 된 추상 메서드도 허용하지 않는 이유는 무엇입니까?
Pacerier 2014-08-23

8
이 설명을 자주 읽었지만 IMHO가 잘못되었습니다. 인터페이스는 OOP, 통신 API 또는 하드웨어에 대해 이야기하더라도 일종의 "표준 교환 프로토콜"입니다. 내 PC의 USB 포트는 분명히 공용 인터페이스입니다. 그러나 USB 포트 옵션에 대한 액세스를 제공하는 키 잠금 케이스 뒤에있는 메인 보드의 핀은 분명히 "보호 된"인터페이스입니다. 그런 다음 BIOS 칩이 있습니다.이 칩은 표준화 된 인터페이스이기도하지만 어떤 식 으로든 공개되지 않았으며 정확한 세부 정보를 비공개로 알고있는 회사는 소수에 불과합니다. 물론 인터페이스는 모든 가시성을 가질 수 있습니다! 왜 OOP에 있지 않습니까?
Foo Bar

55

자주 인용되는 이유는 "인터페이스가 공용 API를 정의"하기 때문이지만, 이는 지나치게 단순화 된 것이라고 생각합니다. (그리고 그것은 순환 논리의 "냄새"이기도합니다.)

액세스 수정자가 혼합 된 인터페이스를 갖는 것은 의미가 없습니다. 예를 들어 부분적으로 공개되고 부분적으로 인터페이스와 동일한 패키지의 다른 클래스로 제한됩니다. 사실, 어떤 경우에는 IMO가 매우 유용 할 수 있습니다.

사실, 난의 일부라고 생각 추론 암시 적으로 공개 인터페이스의 제작 회원 뒤에이 있다는 것이다 는 자바 언어 간단합니다 :

  • 암시 적 공용 인터페이스 멤버는 프로그래머가 처리하기가 더 간단합니다. 메소드 액세스 수정자가 무작위로 선택된 코드 (클래스)를 몇 번이나 보셨습니까? 많은 "일반"프로그래머는 Java 추상화 경계를 관리하는 가장 좋은 방법을 이해하는 데 어려움을 겪습니다 1 . 공용 / 보호 / 패키지-개인을 인터페이스에 추가하면 인터페이스가 더욱 어려워집니다.

  • 암시 적으로 공용 인터페이스 멤버는 언어 사양을 단순화하므로 Java 컴파일러 작성자 및 Reflection API를 구현하는 사람들의 작업이됩니다.

"인터페이스가 공용 API를 정의한다"는 생각은 언어 디자인 결정을 단순화 한 결과 (또는 특성) 일 것입니다. 그 반대는 아닙니다. 그러나 실제로는 두 가지 생각이 Java 디자이너의 마음 속에서 병렬로 발전했을 것입니다.

여하튼 JDK-8179193 의 RFE에 대한 공식적인 응답 은 Java 디자인 팀이 인터페이스 를 허용 하는 것이 실질적인 이점이 거의없이 복잡성을 추가 한다고 2 결정했음을 분명히합니다 protected. 증거찾기 위해 @skomisa에게 찬사를 보냅니다 .

RFE의 증거가 문제를 해결합니다. 그것이 추가되지 않은 공식적인 이유입니다.


1-물론, 최고 수준의 프로그래머는 이러한 일에 어려움이 없으며 더 풍부한 액세스 제어 기능 팔레트를 환영 할 수 있습니다. 그러나 유지 관리를 위해 코드가 다른 사람에게 넘겨지면 어떻게됩니까?

2-당신은 그들의 결정이나 그들의 진술 된 이유에 동의하지 않을 수 있지만 그것은 논쟁의 여지가 있습니다.


21

이 질문은 Java 8의 기본 메소드 도입으로 다시 열렸다고 말해야합니다. 지금 작업중인 프로젝트는 인터페이스의 기본 특성과 유사하며 구현 의도를 추상화하기위한 것입니다.

"기본 보호"메서드를 사용하여 코드를 대폭 단순화 할 수있는 몇 가지 경우가 있습니다. 인터페이스가 여전히 Java 7 논리에 충실하기 때문에 실제로 작동하지 않는 것으로 나타났습니다. 위에서 언급 한 이유로 정상적인 보호 방법은 특별히 의미가 없습니다. 그러나 기본 공용 메서드에 변경 가능성이없고 보호 된 메서드에서 제공 할 수있는 저수준 리소스가 필요한 경우 "기본 보호"작업을 사용하면 더 깨끗한 코드를 유지할뿐만 아니라 향후 사용자를 다음으로부터 보호 할 수 있습니다. 우발적 학대.

(이것은 내가 여전히 불필요한 추상으로 내 코드를 지나치게 복잡하게 만들 필요가 있다는 사실을 비극적으로 바꾸지는 않는다. 그러나 나는 오라클에 기능 요청을 넣을 계획이다.)


100 % 동의합니다. 추상 클래스는 기본 메서드를 도입하기 전에 합리적인 대안이었습니다. 그러나 다중 상속에 대한 제한은 완벽하지 않다는 것을 의미합니다. 기본 메소드가있는 인터페이스는 일반적으로> = JDK 1.8 세계에서 더 나은 대안이지만, 상태를 저장할 수 없기 때문에 상태를 노출하기 위해 다른 추상 메소드를 정의하는 데 의존합니다. 즉, 상태가 항상 공개되는 것은 아닙니다. 당신이 원합니다.
Jeremy Krieg 신부

10

인터페이스는 공용 API를 정의하기 때문입니다. 보호되는 모든 것은 인터페이스에 속하지 않는 내부 세부 사항입니다.

보호 된 추상 메서드와 함께 추상 클래스를 사용할 수 있지만 인터페이스는 공용 메서드 및 공용 정적 최종 필드로 제한됩니다.


5
"인터페이스가 공용 API를 정의하기 때문에"라고 말씀하셨습니다. 그렇다면 인터페이스가 publicAPI 만 정의해야하는 이유는 무엇 일까요? "내부 세부 사항"과 "구현 세부 사항"사이에는 차이가 있습니다. protectedJava 에서는 기본적으로 전 세계인 하위 클래스를 지정할 수있는 모든 사람 에게 공개 공용 인터페이스이므로 확실히 내부 세부 사항이 아닙니다 .
Pacerier 2014 년

1
Java 8의 기본 메소드에서는 더 이상 사실이 아닙니다.
Mario Rossi

@MarioRossi 그리고 Java 9의 개인 인터페이스 메서드에서는 더 이상 사실이 아닙니다.
skomisa

7

아마도 인터페이스 이기 때문에 클라이언트에게 할 수없는 일을 알리기보다는 인스턴스로 할 수있는 일을 클라이언트에게 알리기 위해있을 수 있습니다.


1
나는 왜 인터페이스가 그 구현을 외부 세계에 노출하지 않고서 할 수있는 것을 서브 클래스에게 말할 수 없는지 알지 못한다. 이것은 추상 클래스가 완벽한 대안으로 사용될 수있을 때 내린 디자인 결정이었습니다. 그러나 인터페이스의 기본 메서드의 출현으로 추상 클래스는 이제 불완전한 대안이되었습니다.
Jeremy Krieg 신부

6

나는 강하게 인터페이스 보호 방법을 허용해야한다고 생각; 인터페이스는 전 세계 모든 사람이 볼 수 있어야한다고 누가 말했습니까? "평범한"(읽기 : 무능한) 프로그래머를 혼동 할 수 있다는 점에 관해서 : OOP의 대부분은 객체, 클래스, 패키지 등을 적절하게 구성하는 것입니다. 프로그래머가 모든 작업을 제대로 수행하는 데 어려움을 겪는다면 그는 훨씬 더 큰 문제. Java는 이러한 유형을 위해 만들어졌습니다 .


이것은 질문에 대한 답이 아닙니다.
Stephen C

5

여기에 몇 가지 답변은 순환 추론을 사용하여 인터페이스 메서드를 보호 할 수없는 이유를 설명합니다. 이는 공용이어야하므로 분명히 보호 할 수 없기 때문입니다!

아무 것도 설명하지 않지만 다행히도 누군가 가 몇 년 전에 인터페이스에서 보호 된 메서드에 대한 개선 요청을 JDK 버그 로 제기하여 문제에 대해 밝힙니다.

인터페이스의 보호 된 메서드 : 패키지간에 공유

수정자는 Java에서 약간 제한되어 있으므로 패키지간에 메서드를 공유하는 방법은 공용 메서드로 제한됩니다. 때로는 메소드를 공개하는 것이 위험하지만 적절한 수정자가 없기 때문에 그럴 필요가 있습니다. 내 솔루션은이 한계를 극복합니다.

Java 언어 사양은 현재 인터페이스 메서드에 대한 protected 수정자를 허용하지 않습니다. 이 사실을 활용하고이 새로운 기능에 대한 인터페이스 메서드에 protected를 사용할 수 있습니다.

인터페이스 메서드가 보호 됨으로 표시되고 인터페이스가 다른 패키지의 클래스에 의해 구현되는 경우 메서드는 공용 일 필요는 없지만 개인용이거나 적어도 패키지 보호 대상 일 수도 있습니다. 메서드는 표시됩니다. 클래스가 선언 한 것이 무엇이든 인터페이스의 소스 패키지 (및 하위 패키지?)에서 추가로 표시됩니다.

이렇게하면 잘 알려진 패키지간에 특정 방법을 공유 할 수 있습니다.

그리고 이것은 상태로 마감 된 개선 요청에 대한 응답입니다 Won't fix.

이 제안은 약간의 실제 이득을 위해 복잡성과 특별한 경우를 추가하는 방식으로 문제를 해결하려고합니다. 이 문제를 해결하는 일반적인 방법은 공용 인터페이스를 구현하는 개인 클래스를 갖는 것입니다. 구현 메서드는 공용이지만 전용 클래스 내에 있으므로 전용으로 유지됩니다.

Java 9에서 사용할 수있는 대안은 클래스와 메소드를 공개하는 것이지만 일반 대중에게 내보내는 대신 특정 "친구"모듈에 대한 정규 내보내기가있는 모듈 내에서 가능합니다.

따라서 해당 버그 보고서의 권위있는 내용은 다음과 같습니다.

  • 현재 상황은 변하지 않을 것입니다. 인터페이스는 protected메소드를 지원하지 않을 것입니다 .
  • protected인터페이스에서 메소드를 지원하지 않는 이유 는 " 실제 이득이 거의없는 경우 복잡성과 특수한 경우를 추가 "한다는 것 입니다.
  • Java 9부터 메서드에 대한 패키지 수준 액세스를 제공하는 다른 접근 방식이 있습니다. 사용하여 자바 플랫폼 모듈 시스템 (JPMS을) 에 " "대신에 일반 대중에 수출되는 모듈 친구 메이크업 클래스와 공개 방법,하지만 특정에 자격을 갖춘 수출을 가진 모듈 내 " ".

4

구현 클래스는 인터페이스에 선언 된 모든 메서드를 구현해야하므로 구현 클래스가 다른 패키지에 있으면 어떻게됩니까?


2

인터페이스 설명했던 것과 같은 것을 사용하려면 추상 클래스 또는 중첩 인터페이스를 사용하십시오.

인터페이스 변수에 대한 코드 스타일 에서 발췌 했지만 여전히 메서드에 적용됩니다.

인터페이스는 Java 프로그래머가 자신의 애플리케이션에서 참조하고 구현하기 위해 완전히 액세스 할 수있는 API (Application Programming Interface)를 제공하기위한 것이므로 인터페이스 변수는 암시 적으로 공개됩니다. 인터페이스가 자체와 다른 Java 패키지에서 사용될 수 있기 때문에 공개 가시성을 통해 프로그램 코드가 변수에 액세스 할 수 있습니다.

2

내부 서브 인터페이스를 선언하는 것은 좋은 습관이지만 protected, 기술적으로는 Java의 인터페이스 에서처럼 내부 메소드를 선언 할 수 없습니다 .

물론 공용 인터페이스를 확장하는 내부 용으로 다른 인터페이스를 만들 수 있습니다.

package yourpackage;

public interface PublicInterface {

    public void doThing1();

    public void doThing2();

    public void doThing3();

}

package yourpackage;

interface InternalInterface extends PublicInterface {

    void doAnyInternalThing1();

    void doAnyInternalThing2();

}

InternalInterface패키지 내 에서 인터페이스를 사용할 수 있지만 PublicInterface(공용 메서드에서) 다음 의 모든 하위 유형을 허용해야합니다 .

package yourpackage;

public class SomeClass {

    public void someMethod(PublicInterface param) {
        if (param instanceof InternalInterface) {
            // run the optimized code
        } else {
            // run the general code
        }
    }

}

패키지 외부 사용자는 PublicInterface문제없이 사용할 수 있습니다.

일반적으로 프로그래머는 유사한 상황에서 추상 클래스를 만듭니다. 그러나이 경우 다중 상속의 이점을 잃게됩니다.


1
패키지 외부 사용자도 사용할 수 있습니다 YourPublicInterface.Internal. 중첩 된 인터페이스를 포함하여 인터페이스의 모든 것은 public키워드의 유무에 관계없이 공개 됩니다.
Greg Roelofs

1

의미가있는 유일한 시나리오는 동일한 패키지에 대한 가시성을 제한하려는 경우입니다. 의 다른 모든 용도는 protected적용되지 않습니다. 특히 protected메서드는 하위 항목에 대한 하위 수준 구현의 세부 정보에 대한 액세스를 제공하는 데 자주 사용됩니다. 그러나 노출 할 하위 수준 구현이 없기 때문에 인터페이스에서 선언하는 것은 의미가 없습니다.

그리고 패키지 시나리오조차도 실제로 인터페이스가 무엇인지가 아닙니다.

원하는 것을 얻으려면 두 개의 인터페이스가 필요합니다. 하나는 내부 용이고 다른 하나는 공용 API에 노출됩니다. (내부적 인 것이 가능하지만 반드시 공개적인 것을 확장하는 것은 아닙니다.) 또는 다른 사람들이 지적했듯이 추상 수퍼 클래스입니다.


추상 수퍼 클래스는 패키지 외부의 유형에 의해 파생되는 것을 방지 할 수 있습니다. 패키지 작성자를 신뢰하는 이러한 수퍼 클래스 유형의 참조를받는 사람은 객체가 청구 된대로 동작 할 것이라고 확신 할 수 있습니다. 패키지에 몇 가지 공통 기능을 노출하고 싶지만 적절한 계층 구조에 맞지 않는 여러 클래스가있는 경우 (예 : 하나는 함수 X와 Y, 하나는 Y와 Z, 하나는 X와 Z를 구현) 노출 할 수 있다면 도움이 될 것입니다. 인터페이스를 사용하는 기능은 여전히 ​​인터페이스 유형이 참조하는 인스턴스가 "정품"이 될 것이라고 약속합니다.
supercat 2013 년

0

보호 된 메서드는 하위 클래스가 기본 클래스를 확장하는 경우에만 항상 하위 클래스에서 액세스 할 수 있습니다.

인터페이스의 경우 하위 클래스는 인터페이스를 확장하지 않습니다. 인터페이스를 구현합니다.

보호 된 메서드는 구현이 아닌 extend 를 통해 액세스 할 수 있습니다 .


키워드의 차이는 중요하지 않습니다.
Alex78191

0

인터페이스는 외부 세계에 메서드노출하기위한 것입니다 . 따라서 이러한 방법은 본질적으로 공개됩니다. 그러나 동일한 클래스 계열 내에서 추상화 를 도입하려는 경우 인터페이스와 구현 클래스 사이에 다른 수준의 추상화, 즉 추상 클래스를 만들면됩니다. 아래에 예가 나와 있습니다.

public interface MyInterface {
    public void publicMethod(); // needs to be public
}

public abstract class MyAbstractClass implements MyInterface {
    @Override
    public void publicMethod() {
        protectedMethod(); // you can call protected method here
        // do other stuff
    }
    protected abstract void protectedMethod(); // can be protected
}

public class MyClass extends MyAbstractClass {
    @Override
    protected void protectedMethod() {
        // implement protected method here, without exposing it as public
    }
}

2
그러나 아무도 볼 수없는 개인 메서드는 인터페이스에서 허용됩니다.
Alex78191

자바는 인터페이스에 기본 메소드를 가지고 있습니다. 즉, 인터페이스는 추상 클래스의 다중 상속을 우회하는 버팀목입니다. 그러면 추상 클래스의 다중 상속이 허용됩니다. 기본 방법의 충돌은 문제가되지 않았습니다.
Alex78191

당신이 옳습니다. Java 9부터는 인터페이스에서 개인 메서드가 허용됩니다. 이들은 추상적 일 수 없으며 주로 다른 기본 또는 정적 메서드 (그 자체가 정적 인 경우)에 의해 인터페이스 내에서 구현되고 사용됩니다.
Stefanos Kargas

1
이 대답은 단순히 인터페이스가 보호 된 메서드를 가질 수 없다는 질문을 무시합니다. 보호 된 방법은 여전히 "외부 세계에 방법을 노출" 하고 "이러한 방법은 본질적으로 공개적" 이라는 주장 은 거짓입니다. 언어가 그렇게 설계 되었기 때문에 공개적이지만 인터페이스에서 보호 된 메서드를 허용 할 수 있습니다. OP는 단순히 이유를 묻는 것입니다.
skomisa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.