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 컨테이너를 사용하고 다른 객체에 대해 다른 테이블을 전달해야하는 경우 유용 할 수 있습니다.