Наследования, интерфейсы и абстрактные классы.

Активист

Активист
Команда форума
В общем, есть три листинга, какой будет правильнее использовать в контексте поставленной задачи

Листиг 1
PHP:
<?php
interface client {
	public function add();
} 

class client_base {
	protected function save() {
		// some code here
	}
}

class client_persone extends client_base implements client {
	public function add() {
		// some code here
		$this->save();
	}
}

class client_company extends client_base implements client {
	public function add() {
		// some code here
		$this->save();
	}
}
?>
Листиг 2
PHP:
<?php
abstract class client_base {
	/**
	 * В абстрактном классе мы можем декларировать это
	 * @var bar
	 */
	protected $foo;
	
	/**
	 * phpDOC hear
	 */
	protected function save() {
		// some code here
	}

	/**
	 * В отличии от interface, в абстактом классе мы можем декларировать protected
	 */
	abstract protected function del();
}

class client_persone extends client_base {
	public function add() {
		// some code here
		$this->save();
	}
	
	protected function del() {
		// some code here
	}
}

class client_company extends client_base {
	public function add() {
		// some code here
		$this->save();
	}
	protected function del() {
		// some code here
	}
}
?>
Листиг 3
PHP:
<?php
interface client {
	public function add();
} 

class client_persone implements client {
	public function add() {
		// some code here
		$this->save();
	}	
	protected function save() {
		// some code here
	}
}

class client_company extends client_persone implements client {
	public function add() {
		// some code here
		$this->save();
	}
}
?>
 

zerkms

TDD infected
Команда форума
в контексте поставленной задачи
Где задача-то?

PS: here, person

PPS: если пытаться гадать, то самой удачной реализацией лично мне выглядит вариант 3, только

PHP:
class client_company extends client_persone
без implements
 

craz

Нестандартное звание
гык а де вопрос? или это не вопрос?)
 

Активист

Активист
Команда форума
Вопрос в том, что когда был один "тип клиента" - клиент(физ, юр) в одном лице, потом появился еще один тип клиента "юр", который координатно стал отличаться от обычного типа (физ), собственно - есть решение использовать наследование, но его можно реализовать по-разному, и вот те листинги эту реализацию делают.

zerkms
А чем интерфейс (implements) плох?

В 3-ем листинге вроде код проще, и т.п, но видно, что код допилен после, кроме того, для создания новых типов клиента нет никаких инструкций для программиста (абстраных классов и т.п.).

Или я чего не догоняю в реализации. Сам выбрал вариант 1, но вскрылась проблема, я не могу никуда декларировать некий абстрактный метод (прототип метода) уровня доступа protected (интерфейс как бы для public только), а множественного наследования нет. Этим я хочу заставить самого себя в будущем знать, что из base выпилен метод, и его нужно обязательно описывать дети, но указать это не могу.
 

zerkms

TDD infected
Команда форума
Активист
Тем, что ты уже реализовал его, в иерархии на 1 уровень выше.
 

melo

однажды
Мне нравица реализация с абстрактным классом, в него можно вынести общие вещи для всех наследников.

А в третьем варианте
PHP:
class client_company extends client_persone implements client
зачем тут имплементс, если он реализован у client_persone?

и person)
 

zerkms

TDD infected
Команда форума
melo
Если наследники действительно принадлежат одной иерархии наследования (т.е. наследование применено правильно и к месту), и базовый класс так и так включает все эти методы (которые в наследниках лишь будут уточнены) - тогда смысла выделять абстрактный класс совершенно нет.
 

itprog

Cruftsman
я тоже за второй вариант,

третий вариант как бы говорит "клиент компания является клиентом человеком", что в реальности не совсем так
 

atv

Новичок
Ничто не мешает сделать так:
PHP:
interface client {
    public function add();
} 

abstract class client_base  implements client  {
    protected function save() {
        // some code here
    }
}
//и т.д.
Интерфейсы и абстрактные классы решают немного разные задачи, и вполне могут использоваться совместно, если такая задача возникла.
 

Gas

может по одной?
А вот объясните, зачем для описания интерфейса одной сущности плодить и интерфейс, и абстрактный класс.

В моём понимании нужно использовать или/или. Нужна общая реализация методов - абстрактный класс, не нужна или это описание поведения (enumerable, countable, playable и т.д.) - интерфейс, а вот и интерфейс client + класс client_base - не понимаю.
 

флоппик

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

Gas

может по одной?
флоппик
ну это я понимаю, я просто не вижу смысла, да и как-то не встречал примеров одновременного использования интерфейса и абстрактного класса, для описания _одной и той-же сущности_, как в примере Активист'а.
 

melo

однажды
zerkms
а если нет необходимости создавать экземпляр класса родителя и ты как бы хочешь, чтоб этот объект нельзя было создать, то не стоит делать его абстрактным? Если родительский класс сам по себе как бы лишен смысла, важны только его наследники?
 

флоппик

promotor fidei
Команда форума
Партнер клуба
А, ну да, извини, контекст вопроса не прочел.
 

zerkms

TDD infected
Команда форума
melo
Вот потому, чтобы не было таких тонны "а что если" - нужно задавать вопрос, а не выплёвывать тупо код и предлагать выбрать.
 
Сверху