Абстрактные свойства PHP

К сожалению, охват этого поля ввода в современных браузерах очень низок:

http://caniuse.com/#feat=input-number

Поэтому я рекомендую рассчитывать на резервную копию и полагаться на загруженный с тяжелой загрузкой ввод [type = text] для выполнения задания, пока это правило не будет принято.

До сих пор только Chrome, Safari и Opera имели аккуратную реализацию, но все остальные браузеры не работают. Некоторые из них даже не поддерживают десятичные знаки (например, BB10)!

115
задан Tamás Pap 3 October 2011 в 12:28
поделиться

5 ответов

Нет такой вещи, как определение свойства.

Вы можете объявить свойства только потому, что они являются контейнерами данных, зарезервированных в памяти при инициализации.

С другой стороны, функция может быть объявлена ​​(типы, имя, параметры) без определения (тело функции отсутствует) и, таким образом, может быть сделана абстрактной.

«Абстрактный» указывает только на то, что что-то было объявлено, но не определено, и поэтому перед его использованием необходимо определить это, или оно станет бесполезным.

141
ответ дан Emanuil Rusev 3 October 2011 в 12:28
поделиться

Как указано выше, такого точного определения не существует. Однако я использую этот простой обходной путь, чтобы заставить дочерний класс определить «абстрактное» свойство:

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();
  }
}
21
ответ дан ulkas 3 October 2011 в 12:28
поделиться

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;
1
ответ дан Dropa 3 October 2011 в 12:28
поделиться

Я задал себе тот же вопрос сегодня, и я хотел бы добавить свои два цента.

Причина, по которой мы хотели бы иметь свойства 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...
6
ответ дан Marco Pallante 3 October 2011 в 12:28
поделиться

Необходимость абстрактных свойств может указывать на проблемы проектирования. Хотя во многих ответах реализован тип шаблона шаблона , и он работает, он всегда выглядит несколько странно.

Давайте посмотрим на оригинальный пример:

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-контейнер и вам нужно передавать разные таблицы для разных объектов.

5
ответ дан sevavietl 3 October 2011 в 12:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: