2012-05-14 3 views
3

인터페이스를 가지고 놀아보고 실제로 이해할 수없는 것에 관한 질문이 있습니다.Java - 인터페이스 메소드

다음 코드는 실행되지 않습니다. 이는 인터페이스 메서드에서 모든 개체에서 작동하는 메서드가 필요하며 구현 된 메서드에는 문자열 개체 만 허용하도록 변경된 서명이 있습니다.

interface I { 
    public void doSomething(Object x); 
} 

class MyType implements I { 
    public void doSomething(String x) { 
     System.out.println(x); 
    } 
} 

그러나, 다음 코드 블록을 사용하여, 나는이 일을 한 것을보고 충격을 받았다. 우리는 객체를 반환 할 것으로 예상하고 구현 된 메서드는 문자열 객체 만 반환하기 때문에 작동하지 않을 것이라고 생각했습니다. 왜 이것이 작동하고 전달 된 매개 변수와 반환 유형의 두 가지 원칙의 차이점은 무엇입니까? StringObject 때문에

interface I { 
    public Object doSomething(String x); 
} 

class MyType implements I { 
    public String doSomething(String x) { 
     System.out.println(x); 
     return(x); 
    } 
} 

답변

3
public Object doSomething(String x); 

뭔가를 반환해야합니다 구현합니다. 사실, 어떤 종류의 대상이되는 한 사실입니다. 따라서 구현하면

public String doSomething(String x) {stuff} 

실제로는 객체를 반환하기 때문에 괜찮습니다. 그 객체가 반환 할 객체가 항상 String이된다는 사실은 큰 문제가 아닙니다.

첫 번째 예제가 작동하지 않는 이유는 문자열 만 허용하면 개체를 수락하는 것보다 더 제한적이기 때문입니다. 그러나 문자열 만 반환하는 것이 좋습니다.

예를 들어 건물을 페인트하는 계약을 맺었다 고 가정하면 직원을 고용하여 도움을받을 수 있습니다. 이 계약서는 귀하가 얼마나 큰 지에 관계없이 적용되는 화가를 고용 할 것을 요구하지만 어떤 색 페인트를 사용해야 하는지를 명시하지 않습니다. 6 피트 이상의 화가를 고용 한 경우 (즉, 모든 오브젝트 대신 String 만 받아 들인 입력), 계약을 위반하게됩니다. 그러나 파란색 페인트 (문자열 만 반환)만으로 페인트를 선택하는 것은 계약서에서 색상을 지정하지 않았으므로 건물을 페인트해야하기 때문에 괜찮습니다.

2

그것은 작동합니다. 자바 언어 사양에서

+1

여기에 대한 답변은 아닙니다. 그의 첫 번째 예는 똑같은 "캐스트"였다. 그것이 두 번째로 일한 이유는 maress에 의해 설명된다. – keyser

+0

첫 번째 예에서는 던지기가 없다. 인터페이스는 객체를 매개 변수로 사용하는 메소드를 선언합니다. 문자열을 취하는 메서드를 가지는 것은 Object를 가져 오는 것과 동일하지 않습니다. 객체를 취하는 것과 같이 정수 메소드를 문자열 메소드에 전달할 수 있습니까? –

+0

그 대답은 더 많지만, 여전히 그다지 중요하지 않습니다 : p – keyser

2

:

반환 유형 반환 유형은 참조 유형이 있다면 서로를 오버라이드 (override) 방법에 따라 다를 수 있습니다. return-type-substitutability의 개념은 공변 수익률, 즉 하위 유형에 대한 반환 유형의 특수화를 지원합니다.

다른 말로 표현하면 인터페이스의 반환 유형이 String이고 구현 클래스가 Object 인 경우 작동하지 않습니다.

1

첫 번째 예제가 작동하지 않는 이유와 두 번째 예제는 함수 프로토 타입이 이름과 모든 매개 변수에 의해서만 정의되고 반환 유형에는 정의되어 있지 않기 때문입니다. 첫 번째 예제에서는 차이점이 있으므로 컴파일러는 두 가지 다른 함수라고 생각합니다.

두 번째 예제에서 구현 된 함수는 형식을 확장하지 않지만 형식 (String은 Object의 특수화)을 전문으로하므로 작동합니다.

마찬가지로 구현 된 메소드의 가시성을 제한 할 수는 있지만 확장 할 수는 없습니다.

또한 Java에는이 컨텍스트에서 유용한 제네릭이 있습니다.

예 :

interface I<T> 
{ 
    public void doSomething(T x); 
} 

class MyType implements I<String> 
{ 
    public void doSomething(String x) 
    { 
     System.out.println(x); 
    } 
} 
1

방법 서명이 계정에 반환 유형을 고려하지 않습니다. (비록 동일한 서명이지만 다른 반환 유형을 갖는 두 개의 메소드를 선언하는 것은 오류입니다.) 그래서 :

void doSomething(Object) 
void doSomething(String) 

은 단순히 두 가지 방법이며, 누구도 무시하거나 다른

2

이 동작의 원칙은 covariant return type입니다. 이 특별한 경우 오버라이드 형은 원래 선언 된 매개 변수 유형을 "좁힐"수 있습니다.

이것은 String이 서브 클래스 화 Object이므로 ObjectString으로 대체 될 수 있음을 의미합니다.

1

문자열 클래스는 객체 클래스에서 상속되므로이 코드 만 작동합니다.