Цитата:Какой смысл их использовать, если с тем же успехом можно наследоваться от обычных классов
В принципе можно наследоватся от обычного класса и не реализовывать( оставлять пустыми ) методы, которые будут перекрыты в классах потомках, НО! тогда они станут необязательными для реализации. ВАЖНО! если Мы расширяем абстрактный класс и не реализуем его абстрактные методы, то получаем ошибки т.к. реализация обязательна.
Как уже писали выше, "соль" абстракции это возможность реализовать часть методов и запретить создание экземпляров абстракции.
Цитата:Декларация функций? Но ведь для этого есть интерфейсы
Интерфейсы существуют не только для декларации, они как и классы, по сути, являются типом данных. Так же в интерфейсе можно задать область видимости только public, в абстракции можно public, protected, что бывает весьма полезно.
Вобщем в этом коде попытался отразить все выше сказанное:
PHP:
скопировать код в буфер обмена
[spoiler] <?PHP //Абстракция Test abstract class Test { //Константа const SOME_CONST = "some const"; // защищенный метод protected function fooProtected() { return "fooProtected"; } //Абстрактный метод, реализация обязательна abstract public function barAbstract(); } //Интерфейс TypeOneIface interface TypeOneIface { function echoFoo(); } // Два класа расширяющие абстракцию // ключевое слово final говорит о том, что класс финальный и его нельзя расщирять final class TestTwo extends Test implements TypeOneIface { // реализация обязательного метода ( дектует интерфейс ) public function echoFoo() { return self::fooProtected() . " in TestTwo<br>"; } // реализация обязательного метода ( дектует абстракция ) public function barAbstract() { echo "bar in TestTwo<br>"; } } // END_CLASS TestTwo final class TestThree extends Test implements TypeOneIface { // реализация обязательного метода ( дектует интерфейс ) public function echoFoo() { return self::fooProtected() . " in TestThree<br>"; } // реализация обязательного метода public function barAbstract() { echo "bar in TestThree<br>"; } } // END_CLASS TestThree // еще один тестовый класс final class LetsRock { // Принимаем типизированную переменную, тип есть интерфейс TypeOneIface public function echoFoo( TypeOneIface $object ) { echo $object->echoFoo(); } // Принимаем типизированную переменную, тип есть абстракция Test public function echoBar( Test $object ) { echo $object->barAbstract(); } } // Let's Rock! // наши экземпляры $test_two = new TestTwo(); $test_three = new TestThree(); $lets_rock = new LetsRock(); // Константа echo sprintf( "test two const -> %s <br> test three const -> %s<br>", TestTwo ::SOME_CONST, TestThree ::SOME_CONST ); // Рвботаем с объектами $lets_rock->echoFoo( $test_two ); $lets_rock->echoFoo( $test_three ); // Вариант 1 echo "I<br>"; $lets_rock->echoBar( $test_two ); $lets_rock->echoBar( $test_three ); // Вариант 2 echo "II<br>"; echo $test_two->barAbstract(); echo $test_three->barAbstract(); ?> test two const -> some const test three const -> some const fooProtected in TestTwo fooProtected in TestThree I bar in TestTwo bar in TestThree II bar in TestTwo bar in TestThree [/spoiler]
|