Абстрактный класс против интерфейса

Я искал вокруг SO, а также остальную часть Интернета для хорошего ответа, но я не нашел того, что я действительно понимаю. Я собираюсь представить это по-другому, и, надеюсь, ответы помогут и другим.

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

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

Абстрактный класс

abstract class Foo { abstract public function getValue(); abstract public function setValue($value); } class myObj extends Foo { function getValue() { } function setValue($value) { } } 

Интерфейс

 interface Foo { public function getValue(); public function setValue($value); } class myObj implements Foo { function getValue() { } function setValue($value) { } } 

Чтобы возобновить эту идею (глобально, а не подробно):

 inheritance 

это понятие, которое можно extend from something , и, возможно, добавить новую функцию или переопределить какую-либо существующую функцию (по-другому). Но, используя наследование, вы разделяете большую часть кода с родителем. Вы родитель + некоторые другие вещи.

 interface 

представляет некоторые способности (мы говорим, что класс реализует интерфейс, который говорит, что он обладает этими способностями). Интерфейс может быть реализован двумя классами, которые совершенно разные и не передают свой код (за исключением методов, которые они реализуют). Когда A и B реализуют интерфейс C, A не является B, а B не является A.

И одна из причин для interface – это действительно позволить программисту делать то же самое, что они могут делать с мультинаследованием, но без проблем с несколькими наследствами.

Это понятие используется в некоторых языках программирования, таких как JAVA, PHP …

Абстрактные

Абстрактные классы сосредоточены на сходстве вещей.

Люди считаются видными mammal и, как таковые, не считаются типом vehicle .

Интерфейс

Интерфейсы фокусируются на сопоставлении аналогичной функции.

Например: вы являетесь человеком и являетесь mammal типа. Если вы хотите летать, вам понадобится реализовать flying Interface . Если вы хотите стрелять во время полета, вам также необходимо реализовать gun Interface .

См. Примеры ниже:

 abstract class Mammal { protected $age_; //below are functions I think all mammals will have,including people abstract public function setAge($age); abstract public function getAge(); abstract public function eat($food); } class Person extends Mammal { protected $job_; //Person's feature public function setAge($age){ $this->age_ = $age; } public function getAge(){ return $this->age_; } public function eat($food){ echo 'I eat ' ,$food ,'today'; } //People only attribute public function setJob($job){ $this->job_ = $job; } public function getJob(){ echo 'My job is ' , $this->job_; } } //Now a person wants to fly, but they are typically not able to do so. //So we implement an interface interface Plane{ public function Fly(); } //I also want shoot enemy interface Gun{ public function shoot(); } class Person2 extends Mammal implements Plane,Gun{ protected $job_;//Person feature public function setAge($age){ $this->age_ = $age; } public function getAge(){ return $this->age_; } public function eat($food){ echo '<br/>I eat ' ,$food ,' today<br/>'; } //Only a person has this feature. public function setJob($job){ $this->job_ = $job; } public function getJob(){ echo 'My job is ' , $this->job_; } //----------------------------------------- //below implementations from interfaces function. (features that humans do not have). //Person implements from other class public function fly(){ echo '<br/>I use plane,so I can fly<br/>'; } public function shoot(){ echo 'I use gun,so I can shoot<br/>'; } } $People = new Person(); echo '<pre>'; print_r( get_class_methods('People')); echo '</pre>'; echo '<pre>'; print_r( get_class_methods('People2')); echo '</pre>'; $People2 = new Person2(); $People2->setAge(24); echo $People2->getAge(); $People2->eat('egg'); $People2->setJob('PHP devepop'); echo $People2->getJob(); $People2->fly(); $People2->shoot(); 

Короче говоря, интерфейс – это стандартизация набора функций, в то время как абстрактный класс – это базовый скелет для классов.

Я думал об этом раньше, и я мог бы заключить, что интерфейсы являются логически удобной абстракцией чистого абстрактного класса (c ++).

Что касается того, почему вы выбираете интерфейсы над абстрактными классами, я цитирую ( источник c ++, но понятия одинаковы):

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

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