2010-12-29 4 views
3
전문 수 매개 변수 수

우리는 다음과 같은 두 가지 클래스를 가지고 말 :이 유형은 PHP

abstract class Foo { 
    public abstract function run(TypeA $object); 
} 

class Bar extends Foo { 
    public function run(TypeB $object) { 
     // Some code here 
    } 
} 

클래스 b를 입력 클래스의 TYPEA를 확장합니다. 바의

선언 :: 실행()

때 PHP 정말이 끊어 푸 :: 실행()의 그것과 호환되어야합니다 :이 다음과 같은 오류 메시지를 얻을 사용하려고

그것은 매개 변수 유형에 관한 것입니까, 아니면 여기에 요점을 놓치고 있습니까?

+1

'Foo'는 인터페이스가 아니며'run()'은'final'이 아니십니까? –

+0

좋은 지적, Pekka. 그것은 추상적 인 방법입니다. 나는 그것을 바로 잡을 것이다 : –

답변

6

설명하는 동작은 covariance이며 PHP에서는 지원되지 않습니다. 내부를 모르지만 PHP의 핵심이 "유형 힌트"체크를 적용 할 때 상속 트리를 전혀 평가하지 않는다고 의심 할 수 있습니다.

덧붙여서 PHP는 이러한 유형 힌트 (다른 ​​OOP 언어에서 일반적으로 지원되는 기능)에 contravariance을 지원하지 않습니다. 그 이유는 위와 같은 이유 때문일 가능성이 큽니다. 그래서이 작동하지 않습니다 중 하나 http://www.php.net/~derick/meeting-notes.html#implement-inheritance-rules-for-type-hints

+0

스테판에게 감사드립니다. 나는 Java, .NET, SmallTalk 등과 같은 대부분의 다른 OO 언어에서 이것이 작동한다는 것을 알고있다. 그런 다음 내 디자인을 약간 풀고 안전을 위해 반영해야한다고 생각한다. –

+0

나는 이전의 성명서에서 약간 성급한 것 같았다. Java 매개 변수는 사실상 불변이지만 Java가 메소드 과부하를 지원하기 때문에 공 변성이라는 인상을 줄 수 있습니다. –

0

나는 이것이 by design이라고 생각한다 : 이것은 메소드의 기본 동작을 정의하는 추상 정의의 요점이다.

When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child; additionally, these methods must be defined with the same (or a less restricted) visibility.

+0

물론, 그것은 매개 변수 유형이 아니라 메소드 가시성과 관련이있다. –

+0

@Johan : 왜 이것이 메소드 가시성과 관련이 있다고 생각하십니까? –

+0

@Stefan 그는 아마도 제가 인용 한 블록을 언급하고있을 것입니다. 여전히 @Johan, 기본 원칙은 유효 OOP이고 버그가 아닙니다 –

2

이것은 대부분의 OO 주체와 거의 일치하는 것으로 보입니다. PHP는 .Net과 같지 않습니다. 클래스 멤버를 재정의 할 수 없습니다. Foo의 확장자는 이전에 Foo이 사용 된 위치로 미끄러 져야합니다. 즉, 제약 조건을 느슨하게 할 수 없습니다.

간단히 말해서 유형 제약 조건을 제거하는 것이 분명하지만 Bar::run()이 다른 인수 유형을 필요로한다면 실제로는 다른 함수이고 이상적으로 다른 이름을 가져야합니다.

TypeATypeB에 공통점이있는 경우 공통 요소를 기본 클래스로 옮기고이를 인수 제약 조건으로 사용하십시오.

+0

유형을 확장하는 것이 특수화되지 않으므로 구속을 완화하지 않고 조입니다. –

+0

있습니다. 필자가 제안한 것은 기본 클래스를 arg 형식으로 사용하여 모든 하위 클래스 (TypeA 및 TypeB)가 준수하도록하는 것입니다. 물론 그것이 설치 과정에서 가능하다고 가정합니다. –

0

하나는 항상 코드에서 제약 조건을 추가 할 수 있습니다 :

public function run(TypeA $object) { 
    assert(is_a($object, "TypeB")); 

당신은 기억이나 문서해야합니다

abstract class Foo { 
    public abstract function run(TypeB $object); 
} 

class Bar extends Foo { 
    public function run(TypeA $object) { 
     // Some code here 
    } 
} 

그리고 마지막으로 좀 더 많은 정보를 원하시면

특정 유형 제한. 장점은 프로덕션 서버에서 어설 션을 일반적으로 해제하므로 순전히 개발 도구가된다는 것입니다. (실제로 이것은 개발 중에 발견되는 버그 종류 중 하나이며, 무작위로 생산을 혼란시키지 않습니다.)

-1

전체 힌트를 사용할 수는 없지만. selfparent 키워드를 사용하여 특정 상황에서 유사한 것을 시행 할 수 있습니다.

는 PHP - 수동 의견에서 r dot wilczek at web-appz dot de을 인용 : 지금까지 언급되지 않은 어떤

<?php 
interface Foo 
{ 
    public function baz(self $object); 
} 

class Bar implements Foo 
{ 
    public function baz(self $object) 
    { 
     // 
    } 
} 
?> 

당신이 너무 typehint로 '부모'를 사용할 수 있다는 것입니다.인터페이스가있는 예제 :

<?php 
interface Foo 
{ 
    public function baz(parent $object); 
} 

class Baz {} 
class Bar extends Baz implements Foo 
{ 
    public function baz(parent $object) 
    { 
     // 
    } 
} 
?> 

Bar :: baz()는 이제 Baz의 모든 인스턴스를 허용합니다. Bar가 어떤 클래스의 상속인도 아닌 경우 ('확장'없음) PHP에서 치명적인 오류가 발생합니다. '현재 클래스 범위에 상위가없는 경우 부모에 액세스 할 수 없습니다.'