태그 보관물: abstract-class

abstract-class

PHP 추상 속성 { abstract public

PHP에서 추상 클래스 속성을 정의하는 방법이 있습니까?

abstract class Foo_Abstract {
    abstract public $tablename;
}

class Foo extends Foo_Abstract {
    //Foo must 'implement' $property
    public $tablename = 'users';
}


답변

속성을 정의하는 것과 같은 것은 없습니다.

속성은 초기화시 메모리에 예약 된 데이터 컨테이너이므로 선언 만 할 수 있습니다.

반면에 함수는 정의되지 않고 (형, 이름, 매개 변수) 선언 될 수 있으며 (함수 본문 누락), 따라서 추상이 될 수 있습니다.

“Abstract”는 선언되었지만 정의되지 않았 음을 나타낼 뿐이므로 사용하기 전에 정의해야합니다. 그렇지 않으면 쓸모 없게됩니다.


답변

아니요, 컴파일러로이를 강제 할 방법이 없습니다. $tablename변수에 대해 런타임 검사 ( 예 : 생성자에서)를 사용해야 합니다. 예 :

class Foo_Abstract {
  public final function __construct(/*whatever*/) {
    if(!isset($this->tablename))
      throw new LogicException(get_class($this) . ' must have a $tablename');
  }
}

Foo_Abstract의 모든 파생 클래스에 대해이를 적용하려면 Foo_Abstract의 constructor를 만들어 final재정의를 방지해야합니다.

대신 추상 getter를 선언 할 수 있습니다.

abstract class Foo_Abstract {
  abstract public function get_tablename();
}

class Foo extends Foo_Abstract {
  protected $tablename = 'tablename';
  public function get_tablename() {
    return $this->tablename;
  }
}

답변

자식 개체에서 추상 개체 속성을 강제로 선언하려는 경우 속성의 컨텍스트에 따라 static추상 개체 생성자 또는 setter / getter 메서드에서 속성에 대한 키워드 와 함께 상수를 사용하고 싶습니다 . 선택적으로를 사용 final하여 확장 클래스에서 메서드가 재정의되는 것을 방지 할 수 있습니다 .

그 외에는 하위 개체가 재정의 된 경우 상위 개체 속성 및 메서드를 재정의합니다. 예를 들어 속성이 protected부모 에서처럼 선언되고 public자식 에서처럼 재정 의 된 경우 결과 속성은 공용입니다. 그러나 속성이 private부모에서 선언 된 경우 해당 속성은 그대로 유지 private되며 자식이 사용할 수 없습니다.

http://www.php.net//manual/en/language.oop5.static.php

abstract class AbstractFoo
{
    public $bar;

    final public function __construct()
    {
       $this->bar = static::BAR;
    }
}

class Foo extends AbstractFoo
{
    //const BAR = 'foobar';
}

$foo = new Foo; //Fatal Error: Undefined class constant 'BAR' (uncomment const BAR = 'foobar';)
echo $foo->bar;

답변

위에서 언급했듯이 정확한 정의는 없습니다. 그러나이 간단한 해결 방법을 사용하여 자식 클래스가 “abstract”속성을 정의하도록 강제합니다.

abstract class Father
{
  public $name;
  abstract protected function setName(); // now every child class must declare this 
                                      // function and thus declare the property

  public function __construct()
  {
    $this->setName();
  }
}

class Son extends Father
{
  protected function setName()
  {
    $this->name = "son";
  }

  function __construct(){
    parent::__construct();
  }
}

답변

오늘도 같은 질문을했는데 2 센트를 더하고 싶습니다.

abstract속성 을 원하는 이유는 하위 클래스가 속성을 정의하고 그렇지 않은 경우 예외를 던지도록하기 위해서입니다. 내 특정한 경우에는 static동료 와 함께 일할 수있는 무언가가 필요했습니다 .

이상적으로 나는 다음과 같은 것을 원합니다.

abstract class A {
    abstract protected static $prop;
}

class B extends A {
    protected static $prop = 'B prop'; // $prop defined, B loads successfully
}

class C extends A {
    // throws an exception when loading C for the first time because $prop
    // is not defined.
}

이 구현으로 끝났습니다.

abstract class A
{
    // no $prop definition in A!

    public static final function getProp()
    {
        return static::$prop;
    }
}

class B extends A
{
    protected static $prop = 'B prop';
}

class C extends A
{
}

보시다시피, A나는 정의하지 않지만 getter $prop에서 사용합니다 static. 따라서 다음 코드가 작동합니다.

B::getProp();
// => 'B prop'

$b = new B();
$b->getProp();
// => 'B prop'

에서 C, 다른 한편으로는, 나는 정의하지 $prop내가 예외를 얻을 수 있도록 :

C::getProp();
// => Exception!

$c = new C();
$c->getProp();
// => Exception!

getProp() 예외를 얻으려면 메서드를 호출해야하는데 클래스 로딩시 가져올 수 없지만 적어도 제 경우에는 원하는 동작에 매우 가깝습니다.

나는 정의 getProp()final어떤 것을 방지하기 위해 스마트 사람 (6 개월에서 자신 일명)을 할 유혹

class D extends A {
    public static function getProp() {
        // really smart
    }
}

D::getProp();
// => no exception...

답변

코드를 테스트하여 알 수 있듯이 :

치명적인 오류 : 속성은 …에서 추상으로 선언 할 수 없습니다.

아니 없어. 속성은 PHP에서 추상으로 선언 될 수 없습니다.

그러나 getter / setter 함수 추상을 구현할 수 있습니다. 이것이 여러분이 찾고있는 것일 수 있습니다.

속성은 구현되지 않고 (특히 공용 속성) 존재하거나 존재하지 않습니다.

$foo = new Foo;
$foo->publicProperty = 'Bar';

답변

추상 속성의 필요성은 디자인 문제를 나타낼 수 있습니다. 많은 답변이 일종의 Template 메서드 패턴을 구현 하고 작동하지만 항상 이상하게 보입니다.

원래 예를 살펴 보겠습니다.

abstract class Foo_Abstract {
    abstract public $tablename;
}

class Foo extends Foo_Abstract {
    //Foo must 'implement' $property
    public $tablename = 'users';
}

무언가 abstract를 표시하는 것은 필수품임을 나타내는 것입니다. 음, 필수 값 (이 경우) 은 필수 종속성이므로 인스턴스화 중에 생성자에 전달되어야합니다 .

class Table
{
    private $name;

    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function name(): string
    {
        return $this->name;
    }
}

그런 다음 실제로 더 구체적인 명명 된 클래스를 원한다면 다음과 같이 상속 할 수 있습니다.

final class UsersTable extends Table
{
    public function __construct()
    {
        parent::__construct('users');
    }
}

이것은 DI 컨테이너를 사용하고 다른 객체에 대해 다른 테이블을 전달해야하는 경우 유용 할 수 있습니다.