2016-06-07 3 views
2

클래스 유형 힌트가 인터페이스와 100 % 동일해야하는 이유는 무엇입니까?
내 말은 왜 클래스를 타입 힌트로 구현하는 것을 받아 들일 수 없는가? 인터페이스의 힌트 유형

, 그것은 명확하게하려면

<?php 
interface MyInterface 
{ 
    public function doMethod(SomeInterface $a) 
    { 
    } 
} 

class MyClass implements MyInterface 
{ 
    public function doMethod(ClassThatImplementsSomeInterface $a) 
    { 
    } 
} 

오류 : Fatal error: Declaration of MyClass::doMethod() must be compatible with that of MyInterface::doMethod()

클래스 타입 힌트가 SomeInterface 구현 때문에, 나는 그것이 계약을 아프게하지 않습니다 기대합니다.
왜 내가 그것을 원하니? 인터페이스 유연성의 이점 때문입니다.
추상 클래스도 마찬가지입니다.
'do'메소드에 타입 힌트가 없도록 코드를 다시 작성하면 '수정'됩니다.
그러나 어떻게 든 $a의 형식 힌트가 SomeInterface을 구현해야한다는 계약을 정의해야한다고 생각합니다.
그리고 왜 그냥 SomeInterface 인 동일한 유형 힌트를 사용하지 않습니까?
내가 필요로하는 SomeInterface에는 존재하지 않는 방법이 있기 때문입니다.
그럼이 제한 사항은 무엇입니까?

재현 할 codepad : 다른 클래스를 암시 http://codepad.org/2PLd8AmV

+1

몇 가지 정보, 좋은 질문을 추가했습니다! – DanFromGermany

+0

당신의 인터페이스는 "나는이 중 하나를 사용하겠다"고 말하고 구현은 "네, 나는 이것들 중 하나를 대신 사용하고 있습니다"라고 말합니다 ... 질문이 어디 있는지 보지 않습니다 – Dale

답변

2

대답은 당신이 필요 인터페이스가 필요로하는 개체에 의존 할 수 있다는 간단하다.

실제 세계 예제 :

인터페이스 APPLE이 필요합니다.

이제는 I require a GREEN APPLE이라는 클래스를 구현하려고합니다 (여전히 사과입니다!).

누군가 이제 인터페이스를 구현하여 녹색 사과 용 클래스에 넣으려고합니다. 그는 RED APPLE을 넣으려고합니다. APPLE과 호환되지만 GREEN APPLE은 사용할 수 없습니다.

=> 강타, 계약이 깨졌습니다!

코딩 예 : DifferentClassClassThatImplementsSomeInterface 아니기 때문에

interface MyInterface 
{ 
    public function doMethod(SomeInterface $a); 
} 

class MyClass implements MyInterface 
{ 
    public function doMethod(ClassThatImplementsSomeInterface $a) { } 
} 

class DifferentClass implements SomeInterface { } 

$ding = new MyClass(); 
$ding->doMethod(new DifferentClass); 

이것은 작동하지 않을 것입니다!

+0

사실, 제 경우에는 이벤트 리스너에 관한 것입니다. 이것은 문제입니다 : [http://codepad.org/ZKYUYcid](http://codepad.org/ZKYUYcid) ... 제발 좀 봐 ... 나는 타입 힌트를 제거해야하는지 혼란 스럽네요. Listener 클래스의'handle' 메소드 또는'ChangeUserName' 클래스의 타입 힌트를'UserHasLoggedIn' 클래스에서'Event' 클래스로 재 작성해야 할지를 결정합니다. –

+0

아니면,'Listener' 인터페이스를 확장하는'ChangeUserNameInterface'라는 새로운 인터페이스를 코딩하고 그것을'ChangeUserName' 클래스가 구현하도록해야합니까? 하지만 이벤트 리스너가 너무 많아서 이벤트 리스너 인터페이스가 너무 많아서 너무 비싸다고 생각합니다. 지금은 혼란스러워합니다. –

+0

추상 클래스를 사용하여 인터페이스와 다른 클래스를 결합 할 수 있지만 인터페이스가 가장 좋습니다 (설명을 보려면 "loose couling php"를 검색하십시오!). – DanFromGermany

1

유형 계약을 변경합니다. 인터페이스는 "나를 구현하는 모든 것이이 방법에서 특정 유형을 사용해야합니다"라고 말합니다. 실제 구현에서는 메서드가 실제로 다른 형식을 사용해야한다고 말합니다.

"MyInterface"를 구현하는 개체가있는 한 do 메서드가 있다는 것을 알고 있습니다. 또한이 방법은 SomeInterface이되어야하는 하나의 인수를 취한다는 것을 알고 있습니다. 인터페이스 때문에 객체의 특정 사실을 알거나 신경 쓰지 않아도됩니다 (인터페이스의 특정 구현).

그러나 내가 가지고있는 객체가 MyObject 인 경우 해당되지 않습니다! 실제로 ClassThatImplementsSomeInterface 개체가 필요합니다! 내 개체가이 형식이 아니면 내 프로그램이 충돌합니다. 객체를 만드는 팩토리 메서드가있는 경우 임의로 발생할 수 있습니다. 나는 더 이상 MyInterface 객체가 일관된 구현을 가지고 있다고 믿을 수 없으며 전달하려는 인수가 올바른지 확인해야합니다.

발생하는 문제는 클래스와 인터페이스가 제대로 정의되지 않았 음을 나타냅니다. MyObject은 실제로 SomeInterface의 인스턴스가 아닐 수도 있습니다. 또는 SomeInterface은 실제로 ClassThatImplementsSomeInterface을 대신 사용해야합니다.

부록은

코드 예제를 바탕으로, 핸들 함수의 인수를 제거합니다. Listener 개체의 특정 유형에 대한 __construct 인수의 특정 구현은 Event입니다.

interface Event 
{ 
    public function getName(); 
} 

interface Listener 
{ 
    public function handle(); 
} 

class UserHasLoggedIn implements Event 
{ 
    public function __construct($name, $id) 
    { 
     $this->name = $name; 
     $this->id = $id; 
    } 

    public function getName() 
    { 
     return 'UserHasLoggedIn'; 
    } 
} 


class ChangeUserName implements Listener 
{ 
    private $event; 

    public function __construct(UserHasLoggedIn $event) 
    { 
     $this->event = $event; 
    } 

    public function handle() 
    { 

    } 
} 
+0

이것이 it : [http://codepad.org/ZKYUYcid](http://codepad.org/ZKYUYcid) .. 제발 좀 봐 ... 내 문제를 해결하기위한 당신의 제안은 뭐니? –

+1

나는 내 대답에 제안을 추가했다. 당신이하려는 일에 대해 더 많이 알지 못하더라도 제가 드릴 수있는 조언이 제한적입니다. – Schleis

+0

여전히 인터페이스는 이벤트에 대한 계약을 정의하지 않습니다. __construct 매개 변수가 Event 또는 Event 파생 객체가 아닌 경우에는 어떻게해야합니까? 계약을 설정하고 싶습니다 –

관련 문제