programing

PHP 추상 속성

luckcodes 2022. 11. 7. 22:30

PHP 추상 속성

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

abstract class Foo_Abstract {
    abstract public $tablename;
}

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

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

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

한편 함수는 정의되지 않고(함수 본문 누락) 선언(종류, 이름, 파라미터)할 수 있으므로 추상화할 수 있다.

"추상"은 선언된 것일 뿐 정의되지 않았음을 나타냅니다.따라서 사용하기 전에 정의하지 않으면 무용지물이 됩니다.

에서는 ( 시 체크를 컴파일러를 사용하면 (컨스트럭터에서) 실행 시 체크(예를 들어)를 강제할 방법은 없습니다.$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를 Foo_Abstract로 .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 메서드의 속성에 대한 키워드입니다.필요에 따라 를 사용하여 확장 클래스에서 메서드가 재정의되지 않도록 할 수 있습니다.

예: https://3v4l.org/WH5Xl

abstract class AbstractFoo
{
    public $bar;

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

class Foo extends AbstractFoo
{
    //const BAR = 'foobar'; //uncomment to prevent exception
}
$foo = new Foo(); 
//Fatal Error: Undefined class constant 'BAR'

그러나 확장 클래스는 재정의된 경우 부모 클래스의 속성 및 메서드를 재정의합니다.
를 들어,이 ""로 protected부모로 정의되어 있습니다.public클래스에서는 이 확장클클음음음음음음음음음음음 in in in in in in in in in in in in이다.public않은 경우 로 privateprivate확장 클래스에서는 사용할 수 없습니다.

http://www.php.net/ / manual / en / language . oop 5 . static . http://http://www.php.net/

위와 같이 정확한 정의는 없습니다.단, 다음 간단한 회피책을 사용하여 자녀 클래스가 "추상" 속성을 정의하도록 강제합니다.

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();
  }
}

추상적 속성이 필요한 것은 설계상의 문제를 나타낼 수 있습니다.많은 답변이 템플릿 방식 패턴을 구현하고 작동하지만 항상 이상하게 보입니다.

원래의 예를 보겠습니다.

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 컨테이너를 사용하는 경우 개체마다 다른 테이블을 전달해야 하는 경우에 유용합니다.

저는 오늘 같은 질문을 스스로에게 했습니다. 그리고 제 의견을 덧붙이고 싶습니다.

우리가 원하는 이유는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정의하지 않습니다.$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...

코드를 테스트하는 것만으로 알 수 있듯이:

치명적 오류: 속성을 추상이라고 선언할 수 없습니다...3호선

아니, 없어.PHP에서 속성을 추상이라고 선언할 수 없습니다.

단, getter/setter 함수 추상화를 구현할 수 있습니다.이것이 당신이 찾고 있는 것일 수 있습니다.

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

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

PHP 7은 추상적인 "속성"을 만드는 것을 매우 쉽게 합니다.위와 같이 추상 함수를 만들어 만들지만, PHP 7에서는 해당 함수의 반환 유형을 정의할 수 있기 때문에 누구나 확장할 수 있는 기본 클래스를 구축할 때 훨씬 쉬워집니다.

<?php

abstract class FooBase {

  abstract public function FooProp(): string;
  abstract public function BarProp(): BarClass;

  public function foo() {
    return $this->FooProp();
  }

  public function bar() {
    return $this->BarProp()->name();
  }

}

class BarClass {

  public function name() {
    return 'Bar!';
  }

}

class FooClass extends FooBase {

  public function FooProp(): string {
    return 'Foo!';
  }

  public function BarProp(): BarClass {
    // This would not work:
    // return 'not working';
    // But this will!
    return new BarClass();
  }

}

$test = new FooClass();
echo $test->foo() . PHP_EOL;
echo $test->bar() . PHP_EOL;

tablename 값이 개체의 수명 동안 변경되지 않는 경우, 다음은 간단하지만 안전한 구현입니다.

abstract class Foo_Abstract {
    abstract protected function getTablename();

    public function showTableName()
    {
        echo 'my table name is '.$this->getTablename();
    }
}

class Foo extends Foo_Abstract {
    //Foo must 'implement' getTablename()
    protected function getTablename()
    {
        return 'users';
    }
}

여기서 중요한 것은 문자열 값 'users'가 지정되고 자녀 클래스 구현에서 getTablename()으로 직접 반환되는 것입니다.이 함수는 "읽기 전용" 속성을 모방합니다.

이는 가 추가 변수를 사용하는 앞서 게시한 솔루션과 매우 유사합니다.마르코의 해결책도 조금 더 복잡할 수 있지만 마음에 들어요.

추상 클래스에서 정적 속성을 정의할 수 있습니다.

<?php
abstract class Foo {
    private static $bar = "1234";
    
    public static function func() {
        echo self::$bar;
    }
}


Foo::func(); // It will be printed 1234

늦었지만, 은 이 를 사용할 수 .self ★★★★★★★★★★★★★★★★★」static과 같이

<?php
class A { // Base Class
    protected static $name = 'ClassA';
    public static function getSelfName() {
        return self::$name;
    }
    public static function getStaticName() {
        return static::$name;
    }
}

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

echo A::getSelfName(); // ClassA
echo A::getStaticName(); // ClassA

echo B::getSelfName(); // ClassA
echo B::getStaticName(); // ClassB

언급URL : https://stackoverflow.com/questions/7634970/php-abstract-properties