Pull to refresh

Comments 113

А какой именно вариант его использования вы предлагаете? Просто… я люблю простые вещи :) Все должно быть как можно более просто, но не проще :) Если реализовывать декоратор так, это ckmyj усложнит схему, на мой взгляд.
Я не предлагаю — просто поинтересовался. Вы ж просили критики ;)
А на счёт простоты — мне кажется магические методы её как раз и убивают (усложняют восприятие кода), хотя иногда без них никуда.
Я просто не понял, чем вы поинтересовались :)
Декоратор и примесь — это немного разные вещи, если я правильно понимаю. Декоратор добавляет поведение в объект, а примесь — в класс. Декоратор позволяет заворачивать один объект в другой, наращивая функционал. Если рассматривать такое расширение, как вертикальное, то примесь расширяет класс горизонтально, добавляя новое поведение прямо в него, полностью сохраняя существующий интерфейс.

Магические методы действительно немного усложняют все дело в первую очередь потому, что проверки времени компиляции нет и Intellisense тоже обламывается :) Но в целом… Чего еще хотеть от динамических языков? Ведь в этом их гибкость. Если магические методы усложняют, то что можно сказать о Ruby как о языке, в котором, с точки зрения PHP, все магическое?
У каждого метода есть свои преимущества и свои недостатки.

Что касается магических методов, я имел в виду, что они усложняют восприятие кода, делая его не очевидным — сам код они то упрощают.
Про это в топике говорилось. Однако, довольно часто этим «медленно» можно пренебречь — не везде эти миллисекунды заметны и критичны.
Да, да, в начале статьи об этом сказано. Но трэйты не имеют состояния. Это только методы без свойств. Больше похоже на Графт, но тоже не совсем оно.

wiki.php.net/rfc/horizontalreuse
Кстати, как трэйт и графт по-русски? :) Или еще нет аналога?
trait — дословно — черта (незнаю как по русски это будет)
graft — дословно — имплантант (а по нашему встраивание, или инджект xD)
ИМХО, для graft больше подходит «наращивание» или «добавление», а для trait я вижу только «модель».
ИМХО, для graft больше подходит «наращивание» или «добавление», а для trait я вижу только «модель».
Хотя это тот случай, когда понимаешь, а назвать не можешь :)
Встречал перевод trait как типаж.
Здесь идет старческое нытье о том, что это костыль, и что на C++ это вообще не нужно

Далее ( в следующем абзаца ) небольшое рассуждение о том, что php — вообще тормознутый, и все надо писать на asm.

А если серьезно, штука полезная, сам подобным костылем пользуюсь нередко.
В Yii Framework примеси реализованы в виде классов-поведений, н-р есть базовый класс CComponent, на который можно навешивать своих наследников CBehavior. Ещё подобная практика встречалась вроде в Doctrine.
Подход хорош. Так не хватало множественного наследования в PHP.

Мне кажется так более читабельно:

MixingHello::__extend('MixingAggregatorSample');

вместо Mixins\Registry::register
Так не хватало множественного наследования в PHP.
Не холивара ради, но многие с вами не согласятся.
Это потребует загрузки класса примеси для регистрации. А я уже говорил, что мне хотелось бы этого избежать. Кроме того, не совсем понятно, как тогда кешировать вызовы методов агрегатора. Я так понимаю, вы предлагаете от реестра отказаться?
это не реализация множественного наследования, это ближе к шаблонам в С++
ооо щас начнётся, сразу говорю, каждый метод хорош только для решение определённого типа задачи.
ИМХО: множественное наследование — не есть хорошо. Если вы думаете, что в процессе решения какой-то задачи нужно множественное наследование — то скорее всего ваша архитектура не верна. Я лично убедился в этом на практике. Хотя раньше также считал «мне не хватает множественного наследования».
Согласен. Только примеси — не множественное наследование. Вернее, не совсем оно.
примеси афайк — это и есть множественное наследование, ибо имеют доступ к приватным полям. это приводит к излишней жёсткости классовой модели и нарушению принципа инкапсуляции. планируемые в пхп штрихи этого недостатка лишены ибо действуют только через публичный интерфейс,
Просто иметь доступ к приватному полю класса еще не означает наследование. Но на мой взгляд, вы совершенно правы в том, что доступ к приватным полям представляет некоторую опасность. Вообще-то я его реализовал больше для полноты картины, нежели для чего-то существенного. Без него вполне можно обойтись. Вполне достаточно того, что примесь имеет свое состояние и может вызывать, скажем, публичные методы класса, к которому подмешана. Впрочем, необходимость специального оформления агрегатора для поддержки примесей позволяет проектировать его с учетом возможностей, которые вы хотите примесям предоставить. Так что, даже доступ к приватному полю, если вы его планируете и желаете, может не быть большой проблемой.

Кстати, в моей реализации с доступом к приватным полям будут некоторые проблемы :) PHP Reflection не позволяет обратиться к приватному полю класса, определенному в предке через имя класса-потомка. Нужно обращаться через имя класса, в котором приватное поле определено непосредственно. А с этим есть некоторые проблемы производительности (требуется перебирать всю иерархию). С доступом к protected членам проблем нет.
а что же означает? объект и примесь хранят данные в одном объекте и тем самым накладывают друг на друга кучу ограничений. или у тебя для каждой примеси создаётся отдельный объект с состоянием? тогда это никакая не примесь, а агрегация с делегированием.
Да, для каждой примеси внутри объекта-агрегатора создается объект, хранящий состояние примеси. Доступ к этому объекту имеет только слой агрегатора, который отвечает за диспетчеризацию вызовов.

Разумеется, это не настоящая примесь, а только эмуляция, о чем красноречиво говорит заголовок статьи.

Агрегация и делегирование требуют ручной реализации методов агрегированных объектов. В моей реализации все автоматизировано. Агрегация и делегирование — более фундаментальные понятия, чем примесь, которая на них основана. Я бы не стал путать эти понятия.
это не эмуляция, а реализация совершенно другого. и ничего агрегация с делегированием не требует, не выдумывай.
Почему же совершенно другого? Вы можете как-то обосновать свое мнение? Что такого «совсем другого» есть в моей реализации? Что, совсем на примесь не похоже? Ни капельки?

Что касается агрегации с делегированием, реализация методов все же требуется. Приведу два примера агрегирования:
class A {
   public function hello();
}

class B {
   public function hello2();
}


class Aggregator1 {
    private $a;
	private $b;
	
	public function __construct() {
	    $this->a = new A();
		$this->b = new B();
	}
	
	public function hello() {
		$this->a->hello();
	}
	
	public function hello2() {
	    $this->b->hello2();
	}
}

$test = new Aggregator1();
$test->hello();
$test->hello2();

class Aggregator2 {
    public $a;
	public $b;
	
	public function __construct() {
	    $this->a = new A();
		$this->b = new B();
	}
}

$test = new Aggregator2();
$test->a->hello();
$test->b->hello2();


Второй пример Aggregator2 достаточно неуклюж, правда? Не агрегирование, а кошмар какой-то. С таким же результатом можно отдельные объекты иметь.

А первый пример Aggregator1 для добавления в Aggregator1 реализации новых методов helloX() требует их явного определения. Разве не так? Или я вас не так понял?

и ничего агрегация с делегированием не требует, не выдумывай.

Если не возражаете, я бы вас попросил о более уважительном отношении к собеседнику. Возможно, я вас не понял, но, в таком случае, может быть, вы сможете сделать свою точку зрения более понятной?
я уже обосновал в предыдущем сообщении.

первый пример использует делегирование, второй не использует. любой ооп язык поддерживает делегирование без явного объявления методов (__call, doesNotUnderstand, method_missing, __noSuchMethod__)
Насчет «любой ООП язык» можно поспорить. Pascal например, как в варианте Freepascal, так и в Дельфи-варианте не поддерживает делегирование без явного объявления методов. Произвольный метод по имени можно вызвать только через RTTI. С# — аналогично. Вы не можете вызывать произвольный метод объекта просто так, без плясок с бубном. Разве что использовать dynamic модификатор, но это уже совсем другая песня (которая, кстати, не так давно появилась в языке). Я не большой спец в Ява, но, насколько мне известно, этот язык тоже не поддерживает «прямое делегирование». Оно поддерживается только такими языками, как PHP, Ruby, Python, которые не всегда ООП, но просто динамические по своей природе.

По поводу «это не эмуляция, а реализация совершенно другого» вы мне так и не ответили.

По поводу делегирования в моем примере вы отчасти правы. Совершенно верно, в первом варианте используется делегирование + агрегация на статической типизации. Но для достижения функционала примеси мне нужна динамическая типизация, то есть прямое делегирование вызова метода. В PHP оно реализовано через __call. Вот именно такое я и реализовал. А в моем примере с Aggregator1 в него невозможно добавить другой функционал без изменения объекта, что должно быть возможно с примесью.
нельзя поспорить. приведённые языки не являются объектно ориентированными в отличие от руби и питона. динамизм — основа ооп.
Что за бред вы несете?

Wikipedia и авторы языков с вами не согласны.

Идите, расскажите Гослингу и Липперту, что их языки вовсе даже не объектно-ориентированы.

Впрочем, я понял. Вы просто тролль. Сначала мне это показалось даже забавным, а сейчас стало скучновато.
это их половые трудности. автору термина виднее что он означает
Полностью согласен с tenshi. Вы лукавите говоря о неудобстве в предыдущем примере:
class A {
	public function aa() {
		echo __METHOD__ . " called!\n";
	}
}

class B {
	public function bb() {
		echo __METHOD__ . " called!\n";
	}
}

class AggregateDelegate {

	protected $_objects = array();

	public function __construct() {
		$args = func_get_args();
		for ($i = 0, $s = sizeof( $args); $i < $s; $i++) {
			if (!is_object( $args[$i])) {
				throw new Exception( 'Invalid argument!');
			}
			$this->_objects[] = $args[$i];
		}
	}

	public function __call( $name, $args) {
		if (!method_exists( $this, $name)) {
			for ($i = 0, $object; $object = $this->_objects[$i]; $i++) {
				if (method_exists( $object, $name)) {
					return call_user_func_array(
						array( $object, $name),
						$args
					);
				}
			}
		}
	}

}

class C extends AggregateDelegate {

	public function cc() {
		echo __METHOD__ . " called!\n";
	}

}

$c = new C( new A(), new B());
$c->aa();
$c->bb();
$c->cc();


А можно и так:

class C extends AggregateDelegate {

	public function __construct() {
		parent::__construct( new A, new B);
	}

	public function cc() {
		echo __METHOD__ . " called!\n";
	}

}

$c = new C;
$c->aa();
$c->bb();
$c->cc();


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

При этом откуда взялись A и B нас мало волнует. Ибо, как правило, такое может быть нужно именно тогда, когда A и B — 3'd-party (из понятных соображений). А там где «все мое» ваша эмуляция «mixins» вдвойне неоправданна и проблематична… ИМХО.
Так я и не отрицаю. Просто и вы и Господин тролль слишком увлеклись критикой. Я никого не призывал использовать примеси в рабочих проектах. Наоборот, я говорил, что прежде, чем это использовать, нужно хорошенько подумать. Я демонстрировал только интересный концепт, а не проповедовал использование примесей где надо и не надо.
+. Не зря умные дядьки которые проектировали JAVA, отказались от множественного наследования.
А Страуструпп и авторы языков Common Lisp, EuLisp, Curl, Dylan, Eiffel, Logtalk, Object REXX, Scala, OCaml, Perl, Perl 6, Python, и Tcl, видимо, протупили, допустив множественное наследование в том или ином виде в этих языках? :)

Я бы не был столь категоричным. Конечно, множественное наследование имеет свои недостатки. Однако и некоторые достоинства ему тоже присущи. Недостатки же его столь существенны, что начинающим программистам, видимо, лучше вообще его в руки не давать.
Я бы не был столь категоричным

Да, наверное :) просто я как-то считаю JAVA лучшим образцом объектно-ориентированного языка программирования…
А мне C# нравится. Но для меня это не значит, что все остальные языки — менее объектно-ориентированы :)
Дык я не спорю что менее ОО, скорее может быть менее логичны и не такие «стройные», ну это конечно все субъективно. Мой начальник вообще Perl предпочитает любому другому языку, а на JAVA плюется.
Фанатов Brainfuck мне еще встречать не доводилось, но вполне допускаю, что и такие найдутся :)
А кроме java какие ОО(П) языки вам известны в достаточном и одинаковом с java объёме, что бы сравнивать и что бы делать такие выводы?
Хм, в достаточном и ОДИНАКОВОМ объеме ПХП разве что. Знаком с C++, Object Pascal и Smalltalk…
Это допрос?)
Неа, это всего лишь подтверждение того, что делать такие выводы не зная ни единого ООП языка, кроме java бессмысленно :) Ясное дело, что единственный хорошо известный язык и будет «лучшим» образцом.

(php можно не учитывать, этот мусор на ООП не тянет совершенно).
Я думаю, ваше мнение о PHP тоже можно не учитывать :)
Да я даже о себе говорить не буду, просто ради интереса посоветую поискать по запросу «пхп» на хабре, здесь было уже десятка три холиваров на тему «ООП в ПХП» и всегда сходится к одному мнению, что ооп в этом мусоре как пятая нога, ни реализации, ни применения. Особенно если учесть, что ооп себя оправдывает в проектах в десятки (а то и сотню) тысяч строк, а судя по современным проектам (стартапам, хе-хе!) таких насчитываются единицы. Зато о модной теме ООП судачат все, кому не лень и пихают его везде, где ни попадя, при чём в 95% процентах не представляя себе, что это такое и как же его с умом применить. Почитайте эти холивары, там много чего интересного есть в плане статистики и выводов, которые люди делают. Не говоря о применении, уж реализацию обсосали со всех сторон. Там, в этих постах, и будет опровержение вашего вывода.
здесь было уже десятка три холиваров на тему «ООП в ПХП» и всегда сходится к одному мнению, что ооп в этом мусоре как пятая нога, ни реализации, ни применения./blockquote>
Не хочу никого оскорбить, но кто именно высказывал такое мнение? Этот человек/люди имеет опыт программирования на PHP? У него большой опыт программирования в целом? Кто конкретно развел холивар? Школота, купившая инвайт на Хабр за $25 и кричащая «Я — крутой профи», а другие — отстойные недоноски? Это мнение высказывалось аргументировано? Делались сравнения, обобщения, анализ? Или просто так — кинул в пустоту «PHP — гавно» и пошел дальше?

Особенно если учесть, что ооп себя оправдывает в проектах в десятки (а то и сотню) тысяч строк, а судя по современным проектам (стартапам, хе-хе!) таких насчитываются единицы.

То есть, мы говорим уже о том, что ООП вообще не нужен в небольших проектах?
Кстати, а что работа Facebook, Yahoo Bookmarks (Delicious) и Dailymotion на PHP вам недостаточно? Проекты, скажем так, не маленькие. Впрочем, я соглашусь, что сайтов действительно астрономического масштаба на PHP действительно не так уж много. Впрочем, их вообще в мире не так уж много, не так ли?

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

Если вы накидаете мне ссылок, я с удовольствием почитаю. Если, конечно, в этих ссылках не говносрач пустой, а какая-то более-менее взрослая дискуссия с аргументами или хотя бы ссылками на мнения уважаемых людей.
Я представляю что такое ООП в C++ и Object Pascal, этого не достаточно? Javascript и PHP для вас видимо совсем не авторитеты… )
PHP развивается достаточно динамично, PHP 5.3 это уже далеко не 4.3… Так что не надо так категорично… Хотя спорить об ООП в ПХП дело неблагодарное… )
Слова РНР и быстродействие это несовместимые вещи, человек знающий РНР на достаточном уровне никогда не скажет слово «быстродействие» ибо оно (хоть и заметно ниже чем в других языках, особенно компилируемых) НИКОГДА не бывает узким местом!!!
НИКОГДА не бывает узким местом
Ой, да шо вы говорите. Серьёзно?
Если в вашем проекте РНР слабое место, вы выбрали или не тот ЯП или приложение спроектировано криво.
Мы ведь говорим о том, что слабое место — быстродействие, а не PHP. Или уже все поменялось? :)
Я говорю о том что нет смысла измерять быстродействие РНР, ибо когда РНР был использован к месту и грамотно, оно не будет слабым местом. (вот уж удивлён что такие простые истины приходится повторять)
Измерять быстродействие чего бы то ни было бессмысленно, если все в этом чем-то было использовано к месту и грамотно. Весь вопрос в том, что нужно измерить быстродействие, а затем, если оно неудовлетворительно, искать вещи, использованные не к месту или неграмотно.

Если бы были на свете программисты, умеющие использовать ВСЕ БЕЗ ИСКЛЮЧЕНИЯ к месту и грамотно, у нас бы не было программ с багами и тормозами.
«Использовать к месту», «использовать грамотно», «не тот ЯП» — вроде люди взрослые, а ругаетесь как первоклашки в столовке. Использовать надо то, что удобно.

Мне вот удобно сайты на PHP, под винду приложения на C#, а сервера на Java, и с кем бы я не говорил, я найду кучу аргументов что так надо, и не потому что «грамотно» и т.д., а потому что мне так удобно.
Мне кажется, вы не прочитали нашу «перепалку». Она началась с «Слова РНР и быстродействие это несовместимые вещи».
А мне кажется вы прочитали не то что написано, а придрались к словам.

Оптимизация даже одного SQL запроса, в 99% пересилит любую РНР-оптимизацию, по этому замерять скорости разных подходов я не считаю разумным, использовать надо тот который даст читабельный и удобно-поддерживаемый код. В случае если вы пишете свой гугл, там да, каждая милисекунда важна, но разве вы станете писать его на РНР?
Вы все очень правильно говорите. Если вы посмотрите на мои посты, вы увидите, что именно в этом я и пытался убедить Vladson, к сожалению, используя его аррументацию, из-за чего оказался непонятым.
Знаете, я и в PHP и в любом другом языке могу такую муть навернуть, что она любой сервер подвесит намертво на сайтах с одной страничкой :) Вот вам и не бывает быстродействие в PHP узким местом…
Я бы честно сказал — не удобно.
Приместь это смесь декоратора и интерфейса. Точнее примесь это встроенный в обьект интерфейс декоратора( ;=P )
И что делать если одинаковые функции есть как в базовом класе, так и в примесях(нескольких).
Имхо без управления очередность исполнения цепочки — труба.
У меня этот момент объединения классов называется просто — interference
/** interference (Яндекс.Словари — Перевод ABBYY Lingvo)
* 2. сексуальное домогательство, изнасилование

Назвал так, потому что это действительно так.
Да и как физическое явление хорошо подходит.
Совершенно верно. Что делать, если есть одинаковые функции в примеси и основном классе решает язык. В Ruby я так и не понял, какие правила действуют в данном случае. В моей реализации при конфликте имен будет произведен доступ к полю/методу, примесь которого была помешана первой.

Я не хочу сказать, что это хорошо. Это отвратительно. Неоднозначности и сложности такого рода меня всегда раздражают. Но, в принципе, и без примесей в ООП языках достаточно возможностей, которые легко использовать неправильно.
Не думаю, что использовать подобные «архитектурные решения» полезно в проектах. Подумайте о тех людях, кто будет поддерживать этот код, у них задач хватает. Практичней использовать декоратор(о котором все знают), чем обучать команду разработчиков и поддерживать вот это
Я уже отмечал, что декоратор сильно отличается от примесей. Примесь — достаточно стандартный подход в программировании, о котором многие знают. Кто интересуется чем-то помимо своего единственного и неповторимого языка программирования, конечно.

Примеси реализованы в таком фреймворке, как Symfony, например. Думаю, мнение Фабьена достаточно весомый аргумент.

Да и вообще, данная статья не ставила своей целью пропаганду использования примесей везде и всюду. Я просто выполнял упражнение по реализации в языке возможности, в нем изначально отсутствующей. Я вовсе не призываю ее широко использовать или вообще использовать. Это просто упражнение. Практикум. Экзерсис :)
1) я бы за такой фреймворк оторвал руки и ни в коем случае не пустил на бой.
2) пока читал, вспомнил двух знакомых, способных на подобное. у них хоть обе руки оторви — все равно не прекратят такими абстракциями баловаться.

Думать, ребята, надо о поддерживаемости кода. Когда бизнес-логика начинает занимать львиную долю строк в классах, подобное баловство, допущенное на старте проекта, станет вашей постоянной головной болью. А бложик набросать с такой штуковиной — вполне прокатит
в целом согласен, но думаю что область применения подобных техник лежит в другой плоскости: в библиотечных классах и различных апи. вот, например, в доктрине таких «магий» навалом. там это во много оправдано.
любое API должно быть прозрачным как и любая другая часть проекта. в большом проекте может присутствовать несолько API для каждой из подсистем. я бы не стал использовать магическое API даже если это сторонняя библиотека, Doctrine в частности.
взгляните на Zend Framework — там местами не всё так элегантно или иногда мелочевки какой-то не хватает, но вот зато там все ясно и прозрачно.
ну :) хоть это и немного офтоп, но я бы на вашем месте не стал ручаться за «прозрачность» zf. одна диспетчеризация чего стоит. на этот процесс влияет столько внешних факторов: сплошная магия.
вот что будет после:

$this->_forward('some-action');
$this->getRequest()->setDispatched(true);

Это прозрачно? ;)

Я просто хочу сказать что не всегда удается использовать исключительно ясные и прозрачные методы. Но это не значит, что к этому не нужно стремиться.
$request->setActionName($action)
        ->setDispatched(true);

setDispatched(true)
— значит, что запрос был отправлен на диспечирезацию. Другими словами вызывая переход на новый экшн из некого контроллер-экшена, при этом устанавливая этот флаг в true — значит, что этот экшнн не будет включен в цикл дистпечеризации.

Но мне остался непонятнен ваш вопрос о прозрачности цикла диспечеризации?
Я бы оторвал за ветку 1.х — ужас полный. Когда я увидел код 2ой версии, мне даже не верилось, что это один и тот же человек писал =) Кстати во второй ветке я не видел этих извратов, хотя может просто пропустил.
А мне понравилась и первая. Хотя, нельзя отрицать, что код там в целом более монолитен и создает впечатление не модульного, а цельного.
Я бы сказал, что он не создает впечатление а таковым и является =) и вообще код на уровне php4, ООП модель используется довольно слабо, а иногда просто непонятным способом (это, например, про миксины).
И огромный респект Фабиену, за труд в 2х ветке, где фактически все переписано с нуля.
А примеры есть? То, что код вам не понравился, это, конечно, плохо. :)

Но объективные доводы есть какие-нибудь?
UFO just landed and posted this here
UFO just landed and posted this here
Поконкретнее чуть выше.
Не ужас: zf 1.x, symfony 2.x. Это как минимум в плане кода и архитектуры.
ZF 1.x я не сильно изучал, но мне очень не нравится там один момент. require_once везде по коду раскидано. В 2.x они собираются от этого избавиться.

Кстати, модули ZF писались совсем разными людьми и в коде все же прослеживается несколько различные подходы к программированию местами. Так что, если говорить, что нравится код ZF, надо конкретизировать, какой пакет :)
UFO just landed and posted this here
А почему из кирпичей и с нуля? Мне тоже не очень понравилась ZF, но это просто потому, что когда я выбирал между ней и Symfony, я долго пытался разобраться с MVC у Zend, потом прочел доку по Symfony и въехал с полпинка. Так что — чисто субъективно.

Кстати, NetBeans поддерживает быструю разработку для ZF: blogs.sun.com/netbeansphp/entry/zend_framework_support_added
UFO just landed and posted this here
Да, кстати. Точно так и было. Теперь с этой стороны все более-менее в порядке. А глубже пока не лез. Для простых вещей мне своего хватает, а для сложных — жду Symfony2.
Как пример технологии конечно интересно, спасибо за полезную информацию, но ИМХО множественное наследование — зло, тем более в языке где оно не реализовано. Это как стандартное ООП делать на прототайпах в JS :)

В одной книге по программированию были слова Бьерна по поводу того что «Множественное неаследование — это очень мощный но в тоже время опасный инструмент, сильно усложняющий понимание кода, использовать его надо ТОЛЬКО там где оно ДЕЙСТВИТЕЛЬНО необходимо, а таких мест весьма немного».

И я с ним согласен, кроме того большинство задач решаются абсолютно нормально без него если грамотно проектировать.
Если немного закрыть глаза на скорость — то «стандартное» ООП на JS делается изумительно.
Если не закрывать — то пострадает либо стиль кода, либо приват переменые( и вообще переменые с одинаковыми названиями в иерахии классов)

Кстати — те же примеси на js делаются не просто, а очень просто.

А множественное наследование в виде примесей — очень полезная и крайне мощная чтука.
Могу привести пару примеров.
Хотя, конечно, можно сделать тоже самое и без примесей. Но с ними — «каноничней» и, как не странно, прозрачней…

А вообще представим себе что обьект состоит из трех частей. Все три части используются в конечном классе, но друг на друга им совершенно наплевать и вообще они сами по себе не работают.
Собирая как бы из блоков конечный класс и навертывая на него малек функционала получаем конфетку.
Например возьмем ORM как db+query+loger+cache. Каждый компонент умеет только что-то свое — отправлять нативные запросы к БД, парсить «наш» язык запросов, что-то логировать и кешировать.
Конечный класс переводит запрос в понятный базе, на запросы навешивает кеш и логирует медленные запросы.
Можно сделать через различные тама драйвера, декораторы, интерфейсы и враперы.
Можно написать
query(){
cache:run();
query:parse();
log:log(database:query())
}

А можно просто везде определить(интерфейс) функцию query и в конечном класе описать порядок разрешения конфликта имен.

На выходе будет одни и те же фломастеры.
супер, и каждый объект будет жёстко привязан к конкретному логгеру, базе и кэшу. а если хочется закоммитить что-нибудь в другую базу — извольте писать новый орм? х)
На JS надо писать теми средствами и тем «ООП» который там есть — поверьте он ничем не хуже, а иногда даже удобней и этим поражает адептов ООП :)
множественное наследование не нужно. это против природы OOP
Авторы языков C++, Curl, Dylan, Eiffel, Logtalk, Object REXX, Scala, OCaml, Perl, Perl 6, Python, и Tcl с вами несогласны.
как и любое другое наследование
Даешь функциональное программирование! Долой грязное ООП! :)
Вообще, если вы заметили, там смайлик стоит. Т.е. это шутка была. Как и та фраза, на которую я ответил.

А вы вообще понятие о правилах приличия имеете? Или вам эго мешает им следовать? Элементарное понятие об уважении, я смотрю, у вас вообще отсутствует.
Значит, вы плохо подготовлены в теоретическом плане. Наследование — одна из фундаментальных концепций ООП: en.wikipedia.org/wiki/Object-oriented_programming#Fundamental_concepts_and_features

Конечно, еще есть программирование на основе прототипов, но это тоже похоже на наследование, только немного в другом плане.

У вас есть аргументы в защиту вашей точки зрения «наследование не нужно, оно против природы ООП»?
Признаться, вы меня удивили. После вашего тупейшего поста про презервативы на Хабре, я думал, этот аргумент в свою защиту вы не приведете. Что ж, давайте немного подискутируем.

Вы хорошо текст прочли? Алан говорит

At Utah sometime after Nov 66 when, influenced by Sketchpad, Simula, the design for the ARPAnet, the Burroughs B5000, and my background in Biology and Mathematics, I thought of an architecture for programming. It was probably in 1967 when someone asked me what I was doing, and I said: «It's object-oriented programming».


I didn't like the way Simula I or Simula 67 did inheritance (though I thought Nygaard and Dahl were just tremendous thinkers and designers). So I decided to leave out inheritance as a built-in feature until I understood it better.


Он не говорит, что наследование против природы ООП. Он говорит о том, что ему не понравилось, как его реализовали в языках Simula I и Simula 67. То есть, к тому времени, как Алан формулировал свои выводы, наследование уже было «изобретено». Алан также говорит следующее:

So I decided to leave out inheritance as a built-in feature until I understood it better.
.

Вам понятна эта фраза?

Термин «объекто-ориентированный» стал появляться гораздо раньше, чем был изобретен Smalltalk — еще в 50-60 годах. В Sketchpad наследование и объекты уже были (применительно к графическим примитивам, правда, почитайте, что такое Sketchpad), а датируется эта система шестидесятым.

Smalltalk Алана был создан почти на 10 лет позже Симулы. Он вобрал в себя многие ее идеи, но в отличии от Симулы, этот язык полностью динамический (в отличии, от Симулы, где типизация статична).

К чему я веду. При всем моем уважении к Алану Кэю, нельзя говорить о том, что он один-единственный изобрел ООП и он один-единственный имеет право говорить о том, что такое ООП, а что нет, что в нем хорошо, а что плохо. ООП — это парадигма программирования. Она осмысливалась, обсуждалась и формировалась под влиянием множества людей, каждый из которых вносил свой вклад. В шестидесятых Кристен Нюгорд (жаль, что этого великого человека с нами уже нет) выразил свое понимание ООП в Симуле. Через почти десять лет Алан Кэй сделал это в Smalltalk. Каждый из этих людей внес свой вклад в ООП как парадигму программирования. Каждый из них что-то делал по-своему. Никто из них никогда не старался присвоить себе право «изобретателя ООП».

Да, конечно, термин ООП ныне слегка расплывчатый. Но, мне кажется, так бывает всегда, когда формулируется новая концепция, над которой работает множество людей. В 2003 Митчел говорил о том, что термин ООП включает в себя динамические вызовы, абстракцию, полиморфизм и наследование. А чуть позже в 2006 Ли Скотт упоминает только инкапсуляцию, наследование и динамические вызовы.
он говорит, что наследование совсем не является основой ооп и оставлено лишь на всякий случай — типа вдруг пригодится.

алан кей не придумывал ни объекты, ни сообщения. он придумал сам термин ооп. есть существенная разница между языками в которых есть объекты и объектно-ориентированными языками. во втором случае — всё есть объекты, никаких «примитивных значений».

Неужели? Где это он так говорит? Вы вообще прочитали, что я вам написал, или так просто, троллим опять?
php программисты — это такие очень хитрые и изворотливые программисты.
Заинтересованным стоит посмотреть limb-project.com на предмет пакета lmbToolkit.
Имеющим практическую необходимость в использовании Traits стоит собрать PHP-5.4 (trunk) и использовать его там Traits уже есть.
lmbToolkit интересен. Правда, это не совсем то, что примесь, конечно, но все равно было очень любопытно. А вот ветки PHP 5.4, кажется, уже нет: https://svn.php.net/repository/php/php-src/branches/ После долгих дебатов ее ведь, кажется, удалили.
Я имел ввиду trunk. Он собирается как PHP 5.3.99-dev
А про удаление — скорбная новость. Теперь Traits придется ждать еще долго. Итак уже 2 года жду ( с момента публикации патча в internals )
Вижу много ругани, что множественное наследование зло, но примеси ничего общего с множественным наследованием не имеют (если мы говорим про ruby). Каждая новая примесь встраивается в иерархию наследования становясь родителем для текущего класса.
А в чём разница с множественным наследованием? Каждый новый базовый класс тоже встраивается в иерархию наследования, становясь родителем для текущего класса :)
Sign up to leave a comment.

Articles