В чем разница между abstract и interface в php? [duplicate]

6
задан Community 23 May 2017 в 12:26
поделиться

6 ответов

Различия как теоретические, так и практические:

  • интерфейс — это описание некоторых возможностей вашего класса, которые он рекламирует (поэтому можно использовать различные классы, реализующие один и тот же интерфейс). точно так же)
  • абстрактный класс может быть реализацией по умолчанию, содержащей части, которые могут появиться во всех реализациях. Он не обязан реализовывать полный интерфейс

Пример — интерфейс:

// define what any class implementing this must be capable of
interface IRetrieveData {
    // retrieve the resource
    function fetch($url);

    // get the result of the retrieval (true on success, false otherwise)
    function getOperationResult();

    // what is this class called?
    function getMyClassName();
}

Теперь у нас есть набор требований, которые будут проверяться для каждого реализующего это класса. Давайте создадим абстрактный класс и его дочерние элементы:

// define default behavior for the children of this class
abstract class AbstractRetriever implements IRetrieveData {
    protected $result = false;

    // define here, so we don't need to define this in every implementation
    function getResult() {
       return $result;
    }

    // note we're not implementing the other two methods,
    // as this will be very different for each class.
}

class CurlRetriever extends AbstractRetriever {
     function fetch($url) {
         // (setup, config etc...)
         $out = curl_execute();
         $this->result = !(curl_error());
         return $out;
     }
     function getMyClassName() {
         return 'CurlRetriever is my name!';
     }
}

class PhpRetriever extends AbstractRetriever {
     function fetch($url) {
        $out = file_get_contents($url);
        $this->result = ($out !== FALSE);
        return $out;
     }
     function getMyClassName() {
         return 'PhpRetriever';
     }
}

Совершенно другой абстрактный класс (не связанный с интерфейсом) с подклассом, который реализует наш интерфейс:

abstract class AbstractDog {
     function bark() {
         return 'Woof!'; 
     }
}

class GoldenRetriever extends AbstractDog implements IRetrieveData {
     // this class has a completely different implementation
     // than AbstractRetriever
     // so it doesn't make sense to extend AbstractRetriever
     // however, we need to implement all the methods of the interface
     private $hasFetched = false;

     function getResult() {
         return $this->hasFetched;
     }

     function fetch($url) {
         // (some retrieval code etc...)
         $this->hasFetched = true;
         return $response;
     }
     function getMyClassName() {
         return parent::bark();
     }
}

Теперь, в другом коде, мы можем сделать это:

function getStuff(IRetrieveData $retriever, $url) {
    $stuff = $retriever->fetch($url);
}

и нам не нужно беспокоиться о том, какой из ретриверов (cURL, PHP или Golden) будет передан и как они собираются достичь цели, поскольку все они должны вести себя одинаково. Вы могли бы сделать это и с абстрактным классом, но тогда вы ограничиваете себя на основе предка классов, а не его возможностей.

11
ответ дан 8 December 2019 в 05:52
поделиться

Множественное и одиночное наследование:

  • Вы можете наследовать только от одного абстрактного класса
  • Вы можете реализовать несколько интерфейсов

Реализация:

  • Абстрактный класс может фактически иметь функционирующий код. Это позволяет разделить реализацию между дочерними классами
  • . Интерфейс определяет только общедоступные функции-члены. Классы, реализующие один и тот же интерфейс, на самом деле не имеют общего кода.

Это то, что я знаю наизусть.

6
ответ дан 8 December 2019 в 05:52
поделиться

Вот хорошее описание различия между ними:

http://www.supertom.com/code/php_abstracts_and_interfaces.html

Все сводится к тому факту, что extends является отношением «is-a», в то время как -отношения.

1
ответ дан 8 December 2019 в 05:52
поделиться
"An Abstract Class can contain default Implementation, where as an 
Interface should not contain any implementation at all. "

Что касается того, что использовать в реальных приложениях... все зависит от контекста.

Например, на днях здесь был вопрос о реализации игры с использованием PHP. Здесь у них был абстрактный класс, определяющий монстра, и любой монстр мог быть основан на этом абстрактном классе. Это позволяло наследовать свойства монстров по умолчанию.

Принимая во внимание, что для интерфейса вы определяете общие требования к способу «взаимодействия» (извините за использование термина в объяснении) некоторой системы. Пример этого из недавнего проекта, который я сделал. Я реализовал мыльный клиент на php для взаимодействия с мыльным сервером от третьей стороны. Этот интерфейс определяет, какие методы мыла поддерживает сервер, и поэтому любой класс, реализующий мой интерфейс, должен определять эти методы.

1
ответ дан 8 December 2019 в 05:52
поделиться

Метафора, которую я слышал лучше всего, заключалась в том, что абстрактный класс — это полузавершенный класс. Это не сделано; ты еще должен закончить его. Поэтому, когда вы создаете класс, расширяющий абстрактный класс, вы просто завершаете то, что начали в абстрактном классе. По этой же причине вы не можете создать экземпляр абстрактного класса; то, что вы сделали его абстрактным, указывает на его неполноту. Он все еще нуждается в некоторых дополнительных функциях.

Интерфейс просто гарантирует, что в реализующем его классе должны существовать определенные методы, каждый с определенным количеством аргументов. Так что впоследствии программист, использующий класс, реализующий конкретный интерфейс, может быть уверен, что сможет вызывать определенные методы этого класса.

2
ответ дан 8 December 2019 в 05:52
поделиться
Другие вопросы по тегам:

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