2012-03-30 4 views
2
class Food{} 

class Meat extends Food{} 

class Animal{ 
    void feed(Food f){} 
} 

class Lion extends Animal{ 
    void feed(Meat m){} 
} 


void foo(Animal a){ 
    Food f = new Food(); 
    a.feed(f); 
} 

foo(new Lion())으로 보내면 어떻게 될까요? 오류가 발생하지만 설명이 필요하다는 것을 알고 있습니다.여기에서 공동 편차가 안전합니까?

+1

왜 당신이 여기에서 오류가 발생합니다 생각하십니까? 사자의 피드 방법은 동물의 피드 방법보다 우선하지 않으므로 동물의 피드 방법이 foo를 호출합니다. 반환 유형으로 서브 클래스를 사용하려고하지만 팔머 목록에없는 경우 재정의가 발생합니다. – maks

+0

실제로 오류가 발생하지 않습니다. 사자가 음식을 먹겠지 만'동물의 '방법이 부름 받겠지. 라이온의 구체적인 방법은 아니지만 일치하지 않아. –

답변

5

LionMeat을 먹을 수 있지만 시금치 같은 음식을 먹을 수도 있습니다.

LionFood의 어떤 종류도 먹을 수 없다면, Animal의 구현으로 간주 될 수 없습니다.

하위 클래스 및 클래스 상속을 프로그램을 구성하는 수단으로 사용할 때이를 이해하는 것이 중요합니다. 하위 클래스를 인터페이스 또는 수퍼 클래스보다 더 구체적으로 만들지는 않습니다.

문제를 생성하는 대신 문제를 해결하는 방식으로 하위 클래스를 사용하려면이 가이드 라인을 준수해야합니다. All subclasses must be functionally equivalent to the super-class (Liskov Substitution Principle) 즉, 세 가지 다른 데이터베이스에 대한 데이터베이스 액세스를 제공하는 세 가지 클래스가 "기능"이 "데이터베이스 액세스 제공"이기 때문에 공통 클래스의 하위 클래스를 공유 할 수도 있습니다 (또는 공통 인터페이스를 공유 할 수도 있음). 당신의 Lion 예는 부족하다

는 실제 라이온스는 Food의 어떤 종류를 먹지 않기 때문에 Animal 현실 세계의 정의에 따라, 라이온스는 Animal의이 아니라는 것이다. 실제 세계의 라이온스는 알려지지 않은 동물의 일반적인 정의보다 식량 섭취가 더 구체적입니다. 그리고이 실제적인 라이온스를 이라는 하위 클래스로 모델링하는이 기능상의 차이점은이 특정 동물 정의이 적합하지 않음을 나타냅니다.

당신은 쉽게 Animal "음식을 먹는"방법은 뭔가가 "먹는다 또는 음식을 거부합니다" "음식을 먹는"뭔가에서 Animal의 정의를 변경하는 IncompatibleFoodException을 던져함으로써이 문제를 해결할 수 있습니다.

+2

'@ Override '주석이 도움이되는 곳입니다. 'Lion.feed (Meat)'는 아무 것도 무시하지 않습니다. –

2

이것은 원칙적으로 Liskov substitution에 위배되므로 피해야합니다 (에드윈이 말했듯이, 음식을 먹을 수 없다면 동물이 아닙니다).

아마도 처음에는 생각하지 않았지만 실제로는 오류가 발생하지 않고 Lion :: feed 대신 Animal :: feed가 예상대로 호출됩니다.

제목을 다시 읽고 질문에 구체적으로 대답하십시오. 아니요, 공분산은 여기에서 (동작 측면에서 안전하지 않습니다. 구문에 관해서는.). 예에

빠른 복사 및 질문 붙여 넣기 :

class Food{} 

class Meat extends Food{} 

class Animal{ 
    void feed(Food f){ 
     System.out.println("om nom nom"); 
    } 
} 

class Lion extends Animal{ 
    void feed(Meat m) 
    { 
     System.out.println("OM NOM NOM"); 
    } 
} 

public class test 
{ 

    public static void main(String[] args) 
    { 
     foo(new Lion()); 
    } 

    static void foo(Animal a){ 
     Food f = new Food(); 
     a.feed(f); 
    } 

} 

출력 "옴 놈 'NOM은"