Java가 인터페이스에서 개인 멤버를 허용하지 않는 이유는 무엇입니까?


답변:


85

로부터 Java 언어 사양 (액세스 제어) :

"Java 프로그래밍 언어는 액세스 제어를위한 메커니즘을 제공하여 패키지 또는 클래스의 사용자가 해당 패키지 또는 클래스 구현의 불필요한 세부 사항에 의존하지 않도록 방지합니다."

액세스 제어는 구현 세부 정보를 숨기는 것입니다. 인터페이스에는 숨길 구현이 없습니다.


9
인터페이스 내부에 중첩 클래스를 넣을 수 있으므로 인터페이스에 구현을 넣을 수 있습니다. 그렇게하는 것은 매우 잘못되었지만 우리는 할 수 있습니다.
emory

28
Java 9는 인터페이스에서 비공개 메소드를 허용합니다. 기본 메소드 추가 후 논리적입니다. 참조 : bugs.openjdk.java.net/browse/JDK-8071453
Hariharan

3
"그렇게하는 것은 매우 잘못된 것입니다."항상 그렇듯이 상황에 따라 다릅니다.
JacksOnF1re

5
들리는 것처럼 나쁘지 않습니다. 인터페이스의 개인 메서드는 동일한 인터페이스의 기본 메서드로만 액세스 할 수 있습니다. 이점 중 하나는 캡슐화를 중단하지 않고 기본 메서드 구현을 의미있는 작은 함수로 분할하는 데 도움이되는 것입니다.
Henry Pham

48

Java 9에서는 인터페이스의 개인 메서드가 가능합니다.

Java 9 사양

javac 컴파일러 팀은 JDK의 9 b54 빌드로 시작하는 인터페이스의 private 메서드에 대한 컴파일러 지원을 발표하게되어 기쁩니다.


10
@SebiSebi, Java가 라이브 언어라는 것을 깨달은 순간.
Arashsoft

@Arashsoft, OP는 필드를 요구합니다.
Pacerier

19

개인 인터페이스 메소드는 JEP-213의 일부인 Java 9의 일부입니다 . Java 8의 인터페이스는 기본 메소드를 가질 수 있으므로 비공개 메소드를 사용하면 여러 기본 메소드에서 공유 비공개 메소드를 사용할 수 있습니다.


13

Java 8부터 인터페이스는 기본 메소드를 가질 수 있으며 Java 9부터 인터페이스는 동일한 인터페이스의 기본 메소드로만 액세스 할 수있는 개인 메소드를 가질 수 있습니다.


Java-9 인터페이스 기능에 대해 알아두면 좋습니다.
Ravindra babu

9

인터페이스는 인터페이스를 구현하는 모든 클래스에서 제공하는 API를 설명하는 데 사용됩니다. 정의의 인터페이스에는 상태가 없으므로 필드 멤버를 선언 할 필요가 없습니다.


자바 랜드에서 멤버는 필드, 메소드, 생성자 또는 클래스입니다.
emory apr

7

그러한 인터페이스를 구현할 방법이 없습니다. 내가 제시 한 질문에 대한 대답 은 비공개 메소드로 인터페이스를 구현하는 것이 불가능하다는 것을 강력하게 제안합니다.

class OuterClass
{
     void run ( MyInterface x )
     {
           x . publicMethod ( ) ;  // why not?
           x . protectedMethod ( ) ; // why not?
           x . packagePrivateMethod ( ) ; // why not?
           x . privateMethod ( ) ; // why not?
     }

     interface MyInterface
     {
           public abstract void publicMethod ( ) ; // OK

           protected abstract void protectedMethod ( ) ; // why not?

           abstract void packagePrivateMethod ( ) ; // in interface default is public, but why not package private

           private void privateMethod ( ) ; // impossible to implement
     }

     class MyImpl implements MyInterface
     {
           public void publicMethod ( ) { } // ok

           protected void protectedMethod ( ) { } // no sweat

           void packagePrivateMethod ( ) { } // no sweat

           private void privateMethod ( ) { } // not happening
     }
}

아래 코드는 원하는 결과를 얻을 수 있습니다. 모든 방법이 공용이지만 공용 방법 만 사실상 공용입니다. 보호 된 방법은 효과적으로 보호됩니다. packagePrivateMethod는 효과적으로 packagePrivate입니다. privateMethod는 사실상 비공개입니다.

class WorkAround
{
     void run ( MyPrivateInterface x )
     {
           x . publicMethod ( ) ;  
           x . protectedMethod ( ) ; 
           x . packagePrivateMethod ( ) ; 
           x . privateMethod ( ) ; 
     }

     public interface MyPublicInterface { void publicMethod ( ) ; }

     protected interface MyProtectedInterface extends MyPublicInterface { void protectedMethod ( ) ; }

     interface MyPackagePrivateInterface extends MyProtectedInterface { void packagePrivateMethod ( ) ; }

     private interface MyPrivateInterface extends MyPackagePrivateInterface { void privateMethod ( ) ; }
}

6

Java프로그래밍 언어 범위에 따라 선언 된 범위로 private members제한되며 해당 class메서드에 의해서만 액세스 할 수 있습니다 class. 그러나 inteface메서드 본문이 없으므로 .NET 내부에 private 멤버를 선언 할 필요가 없습니다 interface.


4

Java는 Java 9의 인터페이스에서 개인 메서드를 허용 합니다. 기본 방법은 자바 8. 여러 기본 방법이 몇 가지 코드를 공유 할 가능성이 도입되었습니다,이 코드는 외부 세계에 노출하지 않고 개인 방법으로 이동할 수 있습니다. 이 버그 가 수정되어 JDK 9 빌드 54 부터 개인 인터페이스 메서드에 대한 컴파일러 지원이 부활했습니다.

public interface IData{
   default void processData(int data) {
      validate(data);
      // do some work with it
   }
   default void consumeData(int data) {
      validate(data);
      // do some work with it
   }
   private void validate(int data) {
     // validate data
   }
}

3

쓸모 없기 때문입니다.

private 메서드를 호출 할 방법이 없습니다.

개인 멤버는 구현 세부 사항입니다. 인터페이스는 클래스가 맡을 수있는 공용 역할에 관한 것입니다.


"개인 메서드를 호출 할 방법이 없습니다."라는 wrt에 동의하지 않습니다. - 내부 클래스를 사용하는 방법이있을 것입니다 stackoverflow.com/a/10169894/348975
모리

Java 8의 기본 메소드를 고려하십시오. 인터페이스 I에는 많은 공통 코드가있는 기본 메소드 A와 B가 있습니다. 이를 리팩토링하려면 공유 코드 만 포함하고 A와 B에 의해 호출되는 메서드 C가 필요합니다. Java 8에서는 모든 인터페이스 구현 자에게 노출되는 기본 메서드가됩니다. 자바에서 9 C는 I. 내에서 방법을 기본값으로 만 볼 수있는 전용 방법이 될 수있다
이반 크릴 로프

2

private 필드는 다른 필드와 내부 클래스가 액세스 할 수 있으므로 완전히 쓸모가 없습니다.

그러나 중첩 된 클래스에서도 private 메서드를 구현할 수 없으므로 거의 쓸모가 없습니다. 리플렉션을 사용하여 읽을 수는 있지만 그것은 오히려 가장자리의 경우입니다.


여기 무덤 파기 죄송합니다 :( 이 경우 docs.oracle.com/javase/7/docs/api/java/io/Serializable.html 은 어떻게 작동합니까? 사람들이 그것을 구현 한 다음 readObject 및 writeObject 메서드를 덮어 쓸 수 없습니다. ? 나는 확실히 내가 뭔가를 누락 해요
PatrickWalker

1

비공개 멤버는 인터페이스에서 의미가 없습니다. 인터페이스는 해당 클래스의 내부를 볼 필요가없는 정의 된 메서드로 클래스에 액세스하는 방법입니다.

개인 회원은 이에 동의하지 않습니다.


0

private로 선언 된 클래스의 멤버는 해당 클래스의 하위 클래스에서 상속되지 않습니다. protected 또는 public으로 선언 된 클래스의 멤버 만 클래스가 선언 된 패키지가 아닌 패키지에서 선언 된 하위 클래스에 의해 상속됩니다.

소스

따라서 상속 불가능한 개인 필드와 함께 작동 할 수있는 인터페이스에 작업 메서드가 없습니다. 그렇다면 왜 존재해야합니까?


0

네, 할 수 없습니다. 왜 안되는지에 대한 모든 의견 :

인터페이스 I를 사용하는 클래스 A가 있다고 상상해보십시오. 클래스 B는 클래스 A를 확장하므로 A의 모든 인터페이스 메서드도 상속합니다.

이제 내가 클래스 A에 private 메서드를 원하지만 다른 클래스에 대해서도 계약 적으로 정의하고 싶다고 상상해보십시오 (아마도 클래스 B 또는 A를 확장하지 않는 클래스 C).

아마도 I 인터페이스를 사용하는 모든 클래스에 대해 원하는 "초기화"메서드의 경우입니다. 그러나 분명히 나는 ​​초기화 메서드가 공개되는 것을 원하지 않습니다 .... 한 번만 사용하거나 클래스가 필요하다고 판단하는대로 사용해야하기 때문입니다.

유일한 해결책은 해결 방법이거나 인터페이스없이 클래스 자체에 init 메소드를 강제하는 것입니다.

나는 그 이유도 확실히 이해하지 못하지만 여전히 때때로 유용 할 수 있습니다. 분명히 오라클은 JDK 9에서 개인 인터페이스 메서드를 허용한다는 점에 동의합니다.

어쨌든 내가 한 일은 간단한 부울 변수를 배치하는 것이 었습니다. 그러한 방식으로 인터페이스 메서드 (비공개 여야 함)를 한 번 설정 한 후 true (초기화 = true)로 플래그 지정할 수 있습니다. 그런 다음 다시 호출 될 때 메서드는 단순히 아무 작업도 수행하지 않습니다. 이렇게하면 인터페이스 메서드를 공용으로 구현할 수 있지만 생성자 (제 클래스의)가 먼저 메서드를 호출하기 때문에 변수가 true로 설정되어 다시 호출 할 수 없습니다.

그렇지 않으면 클래스의 내부 작업에서만 사용하도록하려면 다른 해결 방법을 시도해야합니다. 아마도 메서드 자체가 플래그를 사용할 때 플래그를 설정하거나 해제 할 수 있습니다. 플래그가 거짓이면 메서드는 아무 작업도 수행하지 않습니다 (누군가 클래스 외부에서 호출 할 때). 그러나 클래스 자체 메서드가이를 호출하면 신속하게 플래그를 true로 설정 한 다음 메서드를 호출 한 다음 플래그를 false ??

결국 일종의 음소거. 아마도 지금은 개인 클래스를 클래스 자체에 배치하고 인터페이스를 모두 잘라내는 것이 더 나을 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.