왜 PHP 특성(PHP 5.4)이 인터페이스를 구현할 수 없는지 궁금합니다.
사용자 1460043의 답변에서 업데이트 => …prequired 클래스를 사용하여 특정 인터페이스를 구현합니다.
난 그게 명백할 수도 있다는 걸 이해한다 왜냐하면 사람들은 만약 그 일이 일어난다면Class A
를 사용하고 있다.Trait T
이 기능을 구현하고 있습니다.interface I
, 보다Class A
를 실장할 필요가 있습니다.interface I
간접적으로 (그리고 이것은 사실이 아니기 때문에)Class A
특성 메서드의 이름을 바꿀 수 있습니다).
제 경우, 제 특성은 해당 특성을 사용하는 클래스가 구현하는 인터페이스에서 호출 메서드입니다.
이 특성은 실제로 인터페이스의 일부 메서드를 구현한 것입니다.그래서 제 특성을 사용하는 모든 클래스가 인터페이스를 구현해야 하는 코드로 “설계”하고 싶습니다.이렇게 하면 인터페이스에서 정의된 클래스 메서드를 사용할 수 있으며 클래스에 존재하는 메서드가 특성으로 확인됩니다.
질문에 대한 답변
정말 짧은 버전은 할 수 없기 때문에 더 간단합니다.형질은 그런 식으로 돌아가지 않아
글을 쓸 때use SomeTrait;
PHP에서는 컴파일러에게 (효과적으로) Atribute에서 코드를 복사하여 사용 중인 클래스에 붙여 넣으라고 지시합니다.
왜냐하면use SomeTrait;
클래스 내에 있기 때문에 추가할 수 없습니다.implements SomeInterface
수업 시간에 다른 곳에 있어야 하기 때문에
“왜 PHP에는 특성이 없는 거죠?“
왜냐하면 그들은 인스턴스화될 수 없기 때문이다.특성은 코드로 참조할 수 있는 오브젝트나 타입이 아니라 실제로는 언어 구성(컴파일러에게 특성 코드를 복사하여 이 클래스에 붙여넣도록 지시하는 것)일 뿐입니다.
그래서 제 특성을 사용하는 모든 클래스가 인터페이스를 구현해야 하는 코드로 “설계”하고 싶습니다.
이는 추상 클래스를 사용하여 적용할 수 있습니다.use
그 특성으로 부터 수업을 연장하는 거죠.
interface SomeInterface{
public function someInterfaceFunction(); }
trait SomeTrait {
function sayHello(){
echo "Hello my secret is ".static::$secret;
} }
abstract class AbstractClass implements SomeInterface{
use SomeTrait; }
class TestClass extends AbstractClass {
static public
$secret = 12345;
//function someInterfaceFunction(){
//Trying to instantiate this class without this function uncommented will throw an error
//Fatal error: Class TestClass contains 1 abstract method and must therefore be
//declared abstract or implement the remaining methods (SomeInterface::doSomething)
//} }
$test = new TestClass();
$test->sayHello();
그러나 특성을 사용하는 클래스가 특정 메서드를 사용하도록 강제할 필요가 있다면 애초에 추상적인 클래스여야 할 특성을 사용하고 있을 수 있습니다.
아니면 당신의 논리가 틀렸거나.인터페이스를 실장하는 클래스는 특정 기능을 가지고 있어야 합니다.특정 기능을 가지고 있는 경우, 그 자체를 인터페이스 실장이라고 선언해야 하는 것은 아닙니다.
편집
실제로 Features 내부에 추상 함수를 정의하여 클래스가 메서드를 구현하도록 강제할 수 있습니다.
trait LoggerTrait {
public function debug($message, array $context = array()) {
$this->log('debug', $message, $context);
}
abstract public function log($level, $message, array $context = array()); }
그러나 인터페이스가 클래스가 이행할 필요가 있는 계약을 정의하는 데 있어서 특성보다 훨씬 우수하기 때문에 특성에서 인터페이스를 구현할 수 없고 설계에도 좋지 않은 냄새가 납니다.
RFC에는 다음과 같은 특징이 있습니다.인터페이스의 특징에 따라 언어에 추가할 필요가 있습니다.
trait SearchItem implements SearchItemInterface {
... }
인터페이스에 필요한 메서드는 특성에 의해 구현될 수도 있고 추상이라고 선언될 수도 있습니다.이 경우 해당 특성을 사용하는 클래스에서 구현될 것으로 예상됩니다.
이 기능은 현재 언어에서는 지원되지 않지만 검토 중입니다(RFC의 현재 상태는 Under Convention).
[…] 내 특성을 사용하는 모든 클래스가 인터페이스를 구현해야 하는 코드로 “설계”할 수 있습니다.이렇게 하면 인터페이스에서 정의된 클래스 메서드를 사용할 수 있으며 클래스에 존재하는 메서드가 특성으로 확인됩니다.
이것은 매우 합리적인 것 같고, 당신의 디자인에 문제가 있다고는 말할 수 없습니다.이 아이디어를 염두에 두고 특성이 제안되었습니다. 다음 두 번째 포인트를 참조하십시오.
- 특성은 동작을 구현하는 일련의 방법을 제공합니다.
- 특성에는 제공된 동작의 매개 변수 역할을 하는 메서드 집합이 필요합니다.
- […]
Schérli et al, 특징:구성 가능한 행동 단위, ECOP’2003, LNCS 2743, 페이지 248–274, Springer Verlag, 2003, 페이지 2
따라서, 「실장」하기 위해서가 아니라, 인터페이스를 필요로 하는 특성이 필요하게 되는 것이 적절하다고 말할 수 있습니다.
PHP에서 이 “트래피드 요구 (실장하기 위한 컨슈머 클래스)” 기능을 사용할 수 없는 이유를 알 수 없지만, 현재는 없는 것 같습니다.
@Danack이 답변에서 언급했듯이, 특성 내의 추상 함수를 사용하여 특성을 사용하는 클래스에서 “요구”할 수 있습니다.안타깝게도 개인 기능으로는 이 작업을 수행할 수 없습니다.
@Danack의 답변에 동의하지만 조금 보완하겠습니다.
정말 짧은 버전은 할 수 없기 때문에 더 간단합니다.형질은 그런 식으로 돌아가지 않아
저는 당신이 요청한 것이 언어 실패보다 디자인상의 문제로 더 명백하게 필요한 경우를 몇 가지 생각할 수 있을 뿐입니다.다음과 같은 인터페이스가 있다고 상상해 보십시오.
interface Weaponize {
public function hasAmmunition();
public function pullTrigger();
public function fire();
public function recharge(); }
인터페이스에 정의되어 있는 함수 중 하나를 구현하지만 프로세스에서는 인터페이스에 정의되어 있는 다른 함수를 사용하는 특성이 생성되어 있습니다.이 특성은 해당 기능을 사용하는 클래스가 인터페이스를 구현하지 않으면 모든 것이 트리거를 풀하지 못한다는 오류가 발생하기 쉽습니다.
trait Triggerable {
public function pullTrigger()
{
if ($this->hasAmmunition()) {
$this->fire();
}
} }
class Warrior {
use Triggerable; }
간단한 해결책은 특성을 사용하는 클래스에 이러한 기능을 구현하도록 강제하는 것입니다.
trait Triggerable {
public abstract function hasAmmunition();
public abstract function fire();
public function pullTrigger()
{
if ($this->hasAmmunition()) {
$this->fire();
}
} }
따라서 그 특성은 인터페이스에 완전히 의존하지 않고 그 기능 중 하나를 구현하기 위한 제안입니다. 왜냐하면 그 특성을 사용할 때 클래스는 추상적인 방법의 구현을 요구할 것이기 때문입니다.
최종 설계
interface Weaponize {
public function hasAmmunition();
public function pullTrigger();
public function fire();
public function recharge(); }
trait Triggerable {
public abstract function hasAmmunition();
public abstract function fire();
public function pullTrigger()
{
if ($this->hasAmmunition()) {
$this->fire();
}
} }
class Warrior implements Weaponize {
use Triggerable;
public function hasAmmunition()
{
// TODO: Implement hasAmmunition() method.
}
public function fire()
{
// TODO: Implement fire() method.
}
public function recharge()
{
// TODO: Implement recharge() method.
} }
제 영어실력을 용서해 주세요.