Обсуждение:Введение, или краткий обзор — различия между версиями

Материал из Deeptown Manual
Перейти к: навигация, поиск
(Re)
м (Re)
 
(не показаны 4 промежуточные версии 2 участников)
Строка 42: Строка 42:
  
 
Ну или другой вариант: другая библиотека присылает некий контейнер, который приходится использовать в текущем модуле. Но вот беда, язык на котором написан "тот" модуль понятия не имеет о замыканиях и соответственно ни о каком методе each() не знает (скажем, используется принцип search-valid-next). А нам таки хочется пользоваться всеми преимуществами примеси Enumerable. Тогда берем и расширяем класс методом each() и добавляем в родители соответствующую примесь:
 
Ну или другой вариант: другая библиотека присылает некий контейнер, который приходится использовать в текущем модуле. Но вот беда, язык на котором написан "тот" модуль понятия не имеет о замыканиях и соответственно ни о каком методе each() не знает (скажем, используется принцип search-valid-next). А нам таки хочется пользоваться всеми преимуществами примеси Enumerable. Тогда берем и расширяем класс методом each() и добавляем в родители соответствующую примесь:
extend TheirWeirdCollection extends Enumerable {
+
<source lang="kpp">
    public const function each(block b) {
+
extend TheirWeirdCollection extends Enumerable {
        for(this.search(); this.valid(); this.next())
+
    public const function each(block b) {
            b(this.current());
+
        for(this.search(); this.valid(); this.next())
    }
+
            b(this.current());
}
+
    }
 +
}
 +
</source>
  
 
И радуемся жизни:
 
И радуемся жизни:
var col = SomeMethod(); //скажем, возвращает этот самый TheirWeirdCollection  
+
<source lang="kpp">
var result = col.select() { |x| x > 5; }; //применяем примесь
+
var col = SomeMethod(); //скажем, возвращает этот самый TheirWeirdCollection  
result.each() { |x| puts(x); } //тут уже конечно не TheirWeirdCollection, а array
+
var result = col.select() { |x| x > 5; }; //применяем примесь
 +
result.each() { |x| puts(x); } //тут уже конечно не TheirWeirdCollection, а array
 +
</source>
  
 
А для написания основного кода надо использовать наследование, как и положено.
 
А для написания основного кода надо использовать наследование, как и положено.
Строка 95: Строка 99:
  
 
ЗЫ. По поводу всей системы предлагаю закончить тут флуд, либо перенести его на форум или в обсуждения блоговых записей.
 
ЗЫ. По поводу всей системы предлагаю закончить тут флуд, либо перенести его на форум или в обсуждения блоговых записей.
 +
 +
--[[Участник:Root|_root]] 11:17, 25 апреля 2008 (EDT)
 +
 +
== И еще Ре ==
 +
 +
Ну при таком раскладе конечно, возможны странные явления. Которые, впрочем, все равно жестко детерминированы и определяются порядком импортирования модулей в третьем модуле. К тому же, как сказал _root, компилятор это дело отловит. Но это уже относится к логике разработки софта. Подобные казусы могут быть и без расширений. Вообще, если разработчик (первого/второго модулей) не индус, то он мог бы (и должен был бы) объявить это расширение приватным. Соответственно, оно распространяется только на сам модуль, но не на модули, его импортирующие. Повторюсь: как правило, расширения применяются "для личного удобства". Если же оно выносится в интерфейс, то это должно оговариваться отдельно (и вообще говоря, тут уже надо наследовать, а не расширять).
 +
 +
В общем и целом, мне кажется что это проблемы идеологии а не инструментов. Любой инструмент может быть использован вовред, и упрекать за это надо человека. Это все равно что утверждать, что С++ это отстой только потому что там можно записать в произвольный блок памяти и уронить программу.
 +
 +
--[[Участник:Korvin|Korvin]] 11:26, 25 апреля 2008 (EDT)

Текущая версия на 19:53, 29 апреля 2008

Тема конфликтов расширений классов не раскрыта.

Содержание

[править] Re

Введение потому так и называется, что оно дает общее представление и не углубляется в детали. Если хочется прочитать подробнее — читайте подробнее. И вообще, что понимаете под конфликтом? --Korvin 04:15, 25 апреля 2008 (EDT).

PS: Представьтесь пожалуйста.

[править] Re

Там тоже не раскрыта.

В прочем раскрыть ее всеравно не получится. Ибо конфликт фундаментальный. Примерно теже проблемы возникают у системы типов Haskell'я при попытке скрестить эту систему типов с компонентностью.

А конфликт прост:

Заводим 2 модуля A и B.

В обоих модулях расширяем класс int методом GetFactorial.

Далие в модуле C пытаемся использовать модули A и B.

Внимание вопрос: GetFactorial из какого модуля использовать будем?

Особенно весело становится если все 3 модуля пишут разные люди.

Еще веселее если изначально в модуле B небыло GetFactorial, а через некоторое время появился.


Сердитый Ученый.

ЗЫ Это я еще копать не начал...

ЗЗЫ С виду язык в целом приличный (видел и сильно хуже), а вот вся остальная система вызывает большие сомнения в работоспособности при попытке запустить ее в большой сети.

[править] Re

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

В целом, расширения не предназначены для написания фундаментального кода. Основная идея в том, чтобы можно было подкрутить класс "под себя", без необходимости перелопачивать код. Ориентировка на то, что тебе дали объект, но ты хочешь от него чего то еще. Если проводить аналогию с тем же Ruby. Тебе возвращают объект, но ты хочешь чтобы он умел производить с собой некоторые действия, скажем выводить некоторую информацию (инспектировать себя). И эту информацию ты используешь в своем коде. Тогда просто создается расширение в котором объявляется необходимый метод. Притом что оно никоим образом не мешает другим пользователям (которые так же могут у себя делать расширения). Альтернатива этому подходу -- написание врапперов и преобразование там где надо. Но это уже изврат, однако. Особенно если надо всего пару фич объявить.

Ну или другой вариант: другая библиотека присылает некий контейнер, который приходится использовать в текущем модуле. Но вот беда, язык на котором написан "тот" модуль понятия не имеет о замыканиях и соответственно ни о каком методе each() не знает (скажем, используется принцип search-valid-next). А нам таки хочется пользоваться всеми преимуществами примеси Enumerable. Тогда берем и расширяем класс методом each() и добавляем в родители соответствующую примесь: <source lang="kpp"> extend TheirWeirdCollection extends Enumerable {

   public const function each(block b) {
       for(this.search(); this.valid(); this.next())
           b(this.current());
   }

} </source>

И радуемся жизни: <source lang="kpp"> var col = SomeMethod(); //скажем, возвращает этот самый TheirWeirdCollection var result = col.select() { |x| x > 5; }; //применяем примесь result.each() { |x| puts(x); } //тут уже конечно не TheirWeirdCollection, а array </source>

А для написания основного кода надо использовать наследование, как и положено.

ЗЫ: Сомнения дело хорошее. До тех пор, пока порождают конструктивные диалоги а не флуд и прочие холивары

--Korvin 09:52, 25 апреля 2008 (EDT)

[править] Re

Еще раз:

Модуль А и модуль Б созданны независимыми разработчиками. Они друг о друге вобще ничего не знают.

Соответственно упорядочить модули А и Б друг относительно друга невозможно.

Они расширили один и тотже класс одним и темже методом.

Теперь третий разработчик импортировал оба модуля А и Б.

Чей метод будет использован?


Сердитый Ученый.

ЗЫ Чем дальше тем сильнее прихожу к выводу что наследование реализаций это вобще зло. Ибо очень сильно связывает систему. ИМХО можно использовать только наследование интерфейсов. Тогда система остается в управляемом состоянии гораздо дольше.

Чтобы не дублировать код можно завести 3 сущьности:

1)Интерфейс. Чистый контракт без каких либо намеков на реализацию.

2)Миксин. Может содержать код и данные. Реализует один или несколько интерфейсов. Может требовать чтобы использующий его тип реализовал один или несколько других интерфейсов нужных миксину для работы.

3)Тип. Может содержать код и данные. Может агрегировать миксины. Реализует один или несколько интерфейсов. Тип расширять нельзя. Ни наследованием ни добавление методов.

ЗЗЫ Не первый год пишу high load системы. Те куски информации что есть на вашем сайте вызывают сомнение что система вобще взлетит под хоть какойнибудь нагрузкой. Подроный анализ делать лень. Тем болие что не все подсистемы описаны.

[править] Re

Скажем так. На уровне виртуальной машины - будет использован тот метод, который загружен последним, т.е. из того модуля, который идет последним в списке импорта. Но это если писать на гайд-ассемблере.

K++ просто ругнется ошибкой method redefinition. На этапе компиляции вся информация о методах есть.

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

--_root 11:17, 25 апреля 2008 (EDT)

[править] И еще Ре

Ну при таком раскладе конечно, возможны странные явления. Которые, впрочем, все равно жестко детерминированы и определяются порядком импортирования модулей в третьем модуле. К тому же, как сказал _root, компилятор это дело отловит. Но это уже относится к логике разработки софта. Подобные казусы могут быть и без расширений. Вообще, если разработчик (первого/второго модулей) не индус, то он мог бы (и должен был бы) объявить это расширение приватным. Соответственно, оно распространяется только на сам модуль, но не на модули, его импортирующие. Повторюсь: как правило, расширения применяются "для личного удобства". Если же оно выносится в интерфейс, то это должно оговариваться отдельно (и вообще говоря, тут уже надо наследовать, а не расширять).

В общем и целом, мне кажется что это проблемы идеологии а не инструментов. Любой инструмент может быть использован вовред, и упрекать за это надо человека. Это все равно что утверждать, что С++ это отстой только потому что там можно записать в произвольный блок памяти и уронить программу.

--Korvin 11:26, 25 апреля 2008 (EDT)

Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
информация
документация
Инструменты