Re[5]: В каждой шутке про ООП...
От: dilmah США  
Дата: 14.05.13 12:00
Оценка:
но в реальности же тебе был нужен вовсе не ООП, а модульность, абстрагирование, инверсия контроля, конкатенирование (когда сложное поведение получается комбинацией независимых, отдельно разрабатываемых кусков)
Re[3]: В каждой шутке про ООП...
От: -n1l-  
Дата: 14.05.13 12:05
Оценка:
Тысяча чертей, я хочу это увидеть!
Re[6]: В каждой шутке про ООП...
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.05.13 16:43
Оценка:
Здравствуйте, dilmah, Вы писали:

D>но в реальности же тебе был нужен вовсе не ООП, а модульность, абстрагирование, инверсия контроля, конкатенирование (когда сложное поведение получается комбинацией независимых, отдельно разрабатываемых кусков)


В реальности мне нужен был подход позволяющий легко описывать окна и взаимодействие с ним. А вот эти ваши "модульность, абстрагирование, инверсия контроля, конкатенирование" мне на фиг не упали. Я тогда о них и не слышал. Идей из книги по виндовс мне более чем хватило. А когда все эти идеи я увидел в С++ мне не пришлось их объяснять (хотя они были сильно иные). Ну, а то что это назвали ООП-ом меня вообще не колышет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: В каждой шутке про ООП...
От: artelk  
Дата: 15.05.13 07:15
Оценка:
A>Но в отношение ООП порядок строго обратный: 4, 3, 2, 1!

Предполагаю, что это основная причина одержимости распространенности ООП.
На мой взгляд, три главные причины распространения ООП (в порядке убывания значимости) следующие:

1. На этапе 4, с которого все начинается, все кажется предельно простым, а бенефитов при этом обещают целую кучу!
2. "Новое платье короля": фуу, да у тебя тут говнокодище, ты что, вообще не понимаешь ООП?!
3. Бенефиты таки есть (по крайней мере, для некоторого подмножества задач).
Re[2]: В каждой шутке про ООП...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 16.05.13 09:56
Оценка:
Здравствуйте, artelk, Вы писали:

A>1. На этапе 4, с которого все начинается, все кажется предельно простым, а бенефитов при этом обещают целую кучу!

A>2. "Новое платье короля": фуу, да у тебя тут говнокодище, ты что, вообще не понимаешь ООП?!
A>3. Бенефиты таки есть (по крайней мере, для некоторого подмножества задач).

Аналогия с шахматами, разбор партии:
Игрок с рейтингом ЭЛО где то в 500 объясняет новичку — "здесь надо не так а вот так"
Эло 1000 — "нет, это отстой и надо вот так"
Эло 1500 — "это отстой, ибо будет мат через 15 ходов"
Эло 2000 — "мата не будет, будет ничья после 10 ходов"
Эло 2500 — "нужно сдаваться, партия уже проиграна"
Re[3]: В каждой шутке про ООП...
От: artelk  
Дата: 17.05.13 11:52
Оценка: +1 :)
Здравствуйте, Ikemefula, Вы писали:

I>Здравствуйте, artelk, Вы писали:


A>>1. На этапе 4, с которого все начинается, все кажется предельно простым, а бенефитов при этом обещают целую кучу!

A>>2. "Новое платье короля": фуу, да у тебя тут говнокодище, ты что, вообще не понимаешь ООП?!
A>>3. Бенефиты таки есть (по крайней мере, для некоторого подмножества задач).

I>Аналогия с шахматами, разбор партии:

I>Игрок с рейтингом ЭЛО где то в 500 объясняет новичку — "здесь надо не так а вот так"
I>Эло 1000 — "нет, это отстой и надо вот так"
I>Эло 1500 — "это отстой, ибо будет мат через 15 ходов"
I>Эло 2000 — "мата не будет, будет ничья после 10 ходов"
I>Эло 2500 — "нужно сдаваться, партия уже проиграна"

Впечатляет. Только я второй день пытаюсь понять, аналогия к чему это?
Можно для особо тупых разжевать?
Re[4]: В каждой шутке про ООП...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 17.05.13 12:08
Оценка: 1 (1)
Здравствуйте, artelk, Вы писали:

Вот сюда смотреть:
A>>>1. На этапе 4, с которого все начинается, все кажется предельно простым, а бенефитов при этом обещают целую кучу!
A>>>2. "Новое платье короля": фуу, да у тебя тут говнокодище, ты что, вообще не понимаешь ООП?!
A>>>3. Бенефиты таки есть (по крайней мере, для некоторого подмножества задач).

I>>Аналогия с шахматами, разбор партии:

I>>Игрок с рейтингом ЭЛО где то в 500 объясняет новичку — "здесь надо не так а вот так"
I>>Эло 1000 — "нет, это отстой и надо вот так"
I>>Эло 1500 — "это отстой, ибо будет мат через 15 ходов"
I>>Эло 2000 — "мата не будет, будет ничья после 10 ходов"
I>>Эло 2500 — "нужно сдаваться, партия уже проиграна"

A>Впечатляет. Только я второй день пытаюсь понять, аналогия к чему это?

A>Можно для особо тупых разжевать?

Аналогия про этапы 1 2 3 4 3 2 1 или как там было. Идейка в том, что понимание растет с опытом, при чем, как водится, растет не линейно а скачками, что естественно дял человека. И на каждом уровне пересматриваешь свои позиции.

У Гегеля это закон отрицания отрицания,т.е. движение по спирали.
Re[3]: В каждой шутке про ООП...
От: artelk  
Дата: 17.05.13 12:53
Оценка:
Здравствуйте, artelk, Вы писали:

A>Здравствуйте, minorlogic, Вы писали:


M>>Если не путать ООП и ООД , тогда все ок.

A>Т.е. можно писать код в ООП парадигме, и при этом дизайн системы может не быть объектно-ориентированным? Оригинально.
A>Конечно же, ООП включает себя ООД.

А если поменять "изучение ООП" на "освоение ООП", возражения будут?
"Освоение" включает в себя развитие способности правильно применять ООП при разработке — т.е. чтобы достичь обещанных бенефитов.
Re: В каждой шутке про ООП...
От: artelk  
Дата: 17.05.13 14:11
Оценка:
И вот накопился у меня вопрос на текущем витке спирали.
Что же есть полиморфизм в ООП?
Из википедии:

Subtype polymorphism, often referred to as simply polymorphism in the context of object-oriented programming, is the ability to create a variable, a function, or an object that has more than one form.


Ага, это Subtype polymorphism. Только нифига непонятно.
Смотрим тут:

subtyping polymorphism (sometimes referred to as dynamic polymorphism) allows a function to be written to take an object of a certain type T, but also work correctly if passed an object that belongs to a type S that is a subtype of T (according to the Liskov substitution principle). This type relation is sometimes written S <: T. Conversely, T is said to be a supertype of S—written T :> S.


Хорошо, только причем тут виртуальные функции, про которые сразу вспоминают, когда заходит речь о полиморфизме ООП?!
Формально, ни причем. Т.е. если в языке есть виртуальные функции — то это уже расширение базовой концепнии ООП (как лямбды в ОО языке C#).
Получается, что под "наследованием" в ООП следует понимаеть исключительно наследование реализации!

Subtype polymorphism зачем-то считается отдельной формей полиморфизма (не ad hoc и не parametric, см. Contents тут).
Выходит, что Gaperton в своем великолепном посте
Автор: Gaperton
Дата: 26.02.08
ошибался, сводя его к параметрическому полиморфизму.
По мне, так это частный случай Bounded parametric polymorphism-а с упрощенным синтаксисом (не нужно явно указывать "генерик" параметр). Но у ООП ведь должен быть свой, особый полиморфизм и свой, особый гуманитарный путь развития!

Переубедите, если неправ...
Re[3]: В каждой шутке про ООП...
От: Кодт Россия  
Дата: 18.05.13 14:59
Оценка:
Здравствуйте, artelk, Вы писали:

A>Т.е. можно писать код в ООП парадигме, и при этом дизайн системы может не быть объектно-ориентированным? Оригинально.

A>Конечно же, ООП включает себя ООД.

Легко!
Как известно, ООП — это замыкания для бедных.
Берём какой-нибудь ФП-проект, интенсивно использующий функции высшего порядка и параметрический полиморфизм.
Тупо транслируем ФВП в интерфейс с единственным методом, а параметрический полиморфизм — в интерфейс с набором методов-примитивов (в ООД это называется "паттерн Стратегия" и "паттерн Шаблонный Метод"; чорт, всё-таки ООД пролез сюда! окей, вычёркиваем полиморфизм; или не вычёркиваем, но обфускиваем, чтобы не было в явном виде ни Стратегий, ни Шаблонных Методов).
Вуаля.

Вот сейчас Курилка замутил тему — Окасаки по-русски
Автор: Курилка
Дата: 07.05.13
. Берём упражнения из книги и переписываем их на java 1.0 в КоролевствеСуществительных, вот и будет ООП без ООД.
Перекуём баги на фичи!
Re[2]: В каждой шутке про ООП...
От: Кодт Россия  
Дата: 18.05.13 15:49
Оценка: 6 (1)
Здравствуйте, artelk, Вы писали:

A>И вот накопился у меня вопрос на текущем витке спирали.

A>Что же есть полиморфизм в ООП?
A>Из википедии:

A>

Subtype polymorphism, often referred to as simply polymorphism in the context of object-oriented programming, is the ability to create a variable, a function, or an object that has more than one form.


<>

Начнём с самого главного: с принципа подстановки Лисков (LSP). Именно по нему проходит граница.

Ад-хок-полиморфизм отличается от параметрического и субтипов тем, что плюёт на LSP.
Как именно это наплевательство реализовано — компилятором ли (перегрузка функций С++, параметры шаблонов С++, классы типов Хаскелла), проверками в рантайме пользователем — printf, if(typeid(p)==...), if(dynamic_cast<T*>(p)), паттерн-матчинг Пролога и Эрланга — это совершенно неважно.
Главное, что набор "съедобных" типов задаётся пользователем и образует плоскую одноуровневую иерархию: "некий аргумент" <- "аргумент конкретного типа".

Параметрический полиморфизм основывается на полиморфизме деталей реализации.
Он не плюёт на LSP, а воспроизводит требования деталей. Если детали функции на субтипах — значит, и вся функция на субтипах и отвечает LSP; если детали только произвольные — значит, и вся функция произвольная.

Полиморфизм субтипов вводит ограничения. Между типами вводится иерархия произвольной глубины (даже если это не классы, а прототипы или диапазоны — только тогда следить за иерархией будет уже не компилятор, а пользователь).
Параметрически полиморфные функции обязаны быть всеядными по LSP — если принимаешь аргумент базового типа, то и любого его наследника примешь.
Переопределения функций (как бы, ad-hoc) — обязаны быть контравариантными по входам и ковариантными по выходам: не зауживать типы аргументов, кроме определяющих, и не расширять тип результата. Тут смысл такой, что у семейства перегруженных функций мысленно есть одна интерфейсная параметрически полиморфная — а она должна отвечать LSP.
Для единственного определяющего аргумента (того, который this) — есть и очень простая (и логически выстроенная!) схема диспетчеризации, и, соответственно, очень простая реализация (таблицы виртуальных функций).
Для нескольких определяющих аргументов (т.е. когда делаем мультиметод) начинаются всякие неоднозначности и страсти.
Мне кажется, именно из-за неоднозначностей мультиметоды и не попали в ООП изначально. А когда нужда в них стала появляться — тут-то и начались все эти фокусы с двойной диспетчеризацией (которая, на самом деле, одна из возможных схем).

Да, ещё один важный момент: для субтипов нет ограничения на количество и ассортимент типов, в отличие от ad-hoc, где количество заранее известно либо ограничено какими-то внезапными факторами (например, подгрузкой модуля, который знает, что делать с данным тэгом варианта).
И, в то же время, есть ограничение на иерархию, в отличие от параметрического.
Перекуём баги на фичи!
Re[4]: В каждой шутке про ООП...
От: artelk  
Дата: 22.05.13 09:48
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Легко!

К>Как известно, ООП — это замыкания для бедных.
К>Берём какой-нибудь ФП-проект, интенсивно использующий функции высшего порядка и параметрический полиморфизм.
К>Тупо транслируем ФВП в интерфейс с единственным методом, а параметрический полиморфизм — в интерфейс с набором методов-примитивов (в ООД это называется "паттерн Стратегия" и "паттерн Шаблонный Метод"; чорт, всё-таки ООД пролез сюда! окей, вычёркиваем полиморфизм; или не вычёркиваем, но обфускиваем, чтобы не было в явном виде ни Стратегий, ни Шаблонных Методов).
К>Вуаля.

Я имел ввиду, что изучение/освоение ООП включает в себя изучение/освоение ООД.
Re[3]: В каждой шутке про ООП...
От: artelk  
Дата: 22.05.13 10:22
Оценка:
Здравствуйте, Кодт, Вы писали:

Мало с чем согласен (или мало что понял). Хотя бы вот: LSP определяется в контексте отношения тип-подтип (и, на самом деле, определяет это отношение); параметрический полиморфизм никакого отношения к этому отношению не имеет.

К>Начнём с самого главного: с принципа подстановки Лисков (LSP). Именно по нему проходит граница.

Не очевидно.

К>Ад-хок-полиморфизм отличается от параметрического и субтипов тем, что плюёт на LSP.

К>Как именно это наплевательство реализовано — компилятором ли (перегрузка функций С++, параметры шаблонов С++, классы типов Хаскелла), проверками в рантайме пользователем — printf, if(typeid(p)==...), if(dynamic_cast<T*>(p)), паттерн-матчинг Пролога и Эрланга — это совершенно неважно.
К>Главное, что набор "съедобных" типов задаётся пользователем и образует плоскую одноуровневую иерархию: "некий аргумент" <- "аргумент конкретного типа".
Не понял.

К>Параметрический полиморфизм основывается на полиморфизме деталей реализации.

Это как?
К>Он не плюёт на LSP, а воспроизводит требования деталей. Если детали функции на субтипах — значит, и вся функция на субтипах и отвечает LSP; если детали только произвольные — значит, и вся функция произвольная.
Можно пример(ы)?

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

К>Параметрически полиморфные функции обязаны быть всеядными по LSP — если принимаешь аргумент базового типа, то и любого его наследника примешь.
Ты о всех параметрически полиморфных функциях говоришь или только об огранниченно-полиморфных с ограничемиями вида ТипПараметра <: Тип?
Если о последних, то они по своему определению всеядны по LSP.

<...>

К>Да, ещё один важный момент: для субтипов нет ограничения на количество и ассортимент типов, в отличие от ad-hoc, где количество заранее известно либо ограничено какими-то внезапными факторами (например, подгрузкой модуля, который знает, что делать с данным тэгом варианта).

А для субтипов нет ограничений внезапными факторами (например, подгрузкой модуля, который знает, какие еще субтипы данного типа бывают)?
Re[4]: В каждой шутке про ООП...
От: Кодт Россия  
Дата: 22.05.13 22:29
Оценка:
Здравствуйте, artelk, Вы писали:

A>Здравствуйте, Кодт, Вы писали:


A>Мало с чем согласен (или мало что понял). Хотя бы вот: LSP определяется в контексте отношения тип-подтип (и, на самом деле, определяет это отношение); параметрический полиморфизм никакого отношения к этому отношению не имеет.


Естественно. И ad-hoc, и параметрический полиморфизм не смотрят на LSP.

К>>Начнём с самого главного: с принципа подстановки Лисков (LSP). Именно по нему проходит граница.

A>Не очевидно.

Вот именно поэтому граница проходит по LSP. Мы ведь хотим разобраться, чем субтипы так отличаются от всего остального.

К>>Ад-хок-полиморфизм отличается от параметрического и субтипов тем, что плюёт на LSP.

К>>Как именно это наплевательство реализовано — компилятором ли (перегрузка функций С++, параметры шаблонов С++, классы типов Хаскелла), проверками в рантайме пользователем — printf, if(typeid(p)==...), if(dynamic_cast<T*>(p)), паттерн-матчинг Пролога и Эрланга — это совершенно неважно.
К>>Главное, что набор "съедобных" типов задаётся пользователем и образует плоскую одноуровневую иерархию: "некий аргумент" <- "аргумент конкретного типа".
A>Не понял.

Если у нас есть семейство функций вида foo(T), включающие foo(int), foo(string), template<class X> foo(X*)
то получается иерархия "что угодно из перечня (int,string,указатель)" <-- int; string; X*
Если в этом семействе есть универсальная ловушка-заглушка — foo(...) или tempate<class T> foo(T), — то корневым типом будет не вариантный, а "вообще что угодно".

В С++ информацию о типе знает компилятор, в хаскелле — отчасти компилятор, отчасти она передаётся в рантайме, в яваскрипте каком-нибудь — всё в рантайме и на пользователе.

К>>Параметрический полиморфизм основывается на полиморфизме деталей реализации.

A>Это как?
К>>Он не плюёт на LSP, а воспроизводит требования деталей. Если детали функции на субтипах — значит, и вся функция на субтипах и отвечает LSP; если детали только произвольные — значит, и вся функция произвольная.
A>Можно пример(ы)?

Параметрический, вытекающий из ad-hoc

На С++
template<class T> void foo(T t) { std::cout << (t+t) << std::endl; }

Для любых подходящих типов делаем два действия
— T2 operator+(T,T) — как правило, перегруженный или определённый компилятором, т.е. ad-hoc
— ostream& operator<<(ostream&,T2) — наверняка перегруженный, т.е. ad-hoc

То же самое на хаскелле
foo :: (Num a, Show a) => a -> IO ()
foo a = putStrLn (show (a+a))

С той разницей, что С++ генерит воплощение шаблона для каждого использованного типа, а хаскелл — единственное воплощение с двумя неявными параметрами: словарём класса Num и словарём класса Show.

Параметрический, на субтипах
struct INumShow // привет хаскеллу
{
  virtual INumShow* twice() = 0; // сейчас наплюём на управление памятью
  virtual std::string show() = 0;
};
void foo(INumShow* t) { std::cout << t->twice()->show() << std::endl; }

В эту функцию мы можем подсунуть не любой тип, для которого определены + и <<, а только участника иерархии INumShow.
Зато этих участников может быть сколько угодно, хоть из сторонней dll позаимствуем (тогда как в первом случае все типы были известны компилятору ещё до линковки).

Кстати, здесь я схитрил: не стал делать мультиметод plus(INumShow*,INumShow*), который был бы определён для пар одинаковых типов, так, как это сделано в классе Num у хаскелла. Потому что сразу встал бы вопрос: а как он определён для неодинаковых типов?
И здесь мы бы получили жирный-прежирный ад-хок. Ну, я об этом уже говорил раньше.

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

К>>Параметрически полиморфные функции обязаны быть всеядными по LSP — если принимаешь аргумент базового типа, то и любого его наследника примешь.
A>Ты о всех параметрически полиморфных функциях говоришь или только об огранниченно-полиморфных с ограничемиями вида ТипПараметра <: Тип?
A>Если о последних, то они по своему определению всеядны по LSP.

Разумеется, я уже про ограниченно-полиморфные начал. Да, именно "по определению".
И можно заметить, что их "по определению" отличается от "по определению" ад-хок и "по определению" подлинно параметрических

К>>Да, ещё один важный момент: для субтипов нет ограничения на количество и ассортимент типов, в отличие от ad-hoc, где количество заранее известно либо ограничено какими-то внезапными факторами (например, подгрузкой модуля, который знает, что делать с данным тэгом варианта).

A>А для субтипов нет ограничений внезапными факторами (например, подгрузкой модуля, который знает, какие еще субтипы данного типа бывают)?

Если не подгрузить модуль с реализацией субтипа, то в системе ничего не изменится, кроме того, что этот субтип нигде не будет фигурировать.
А если не подгрузить модуль с реализацией ад-хок обработчика, то, встретив данный тип, мы пойдём по иному пути. По какому именно? Это уж как захотим, или как получится:
— исключительная ситуация: "неизвестный науке тип"
— ловушка: "by default"
— другой подходящий обработчик

Предвидя вопросы, замечу: в ООП-программах встречаются места с махровым ад-хоком. Это всяческая десериализация (чтение конфигов, фабрики классов по GUID/ProgID/etc...)
Перекуём баги на фичи!
Re[5]: В каждой шутке про ООП...
От: Кодт Россия  
Дата: 22.05.13 22:49
Оценка:
Здравствуйте, Кодт, Вы писали:

A>>Можно пример(ы)?


К>Параметрический, вытекающий из ad-hoc


К>На С++

К>
К>template<class T> void foo(T t) { std::cout << (t+t) << std::endl; }
К>

К>Для любых подходящих типов делаем два действия
К>- T2 operator+(T,T) — как правило, перегруженный или определённый компилятором, т.е. ad-hoc
К>- ostream& operator<<(ostream&,T2) — наверняка перегруженный, т.е. ad-hoc

К>То же самое на хаскелле

К>
К>foo :: (Num a, Show a) => a -> IO ()
К>foo a = putStrLn (show (a+a))
К>

К>С той разницей, что С++ генерит воплощение шаблона для каждого использованного типа, а хаскелл — единственное воплощение с двумя неявными параметрами: словарём класса Num и словарём класса Show.

Да, придумал пример на голом си, практически по мотивам хаскелла.
/* обе функции размещают результат в malloc */
typedef void* (*PLUS_PROC)(void*, void*);
typedef char* (*SHOW_PROC)(void*);

void foo(PLUS_PROC plus, SHOW_PROC show, void* t, FILE* f)
{
  void* tt;
  char* s;

  tt = plus(t,t);
  s = show(tt);
  fprintf(f, "<< %s >>\n", s);

  free(s);
  free(tt);
}

/******* пользовательский код *******/

void* plus_shorts(void* a, void* b)
{
  int* sum;
  sum = (int*)malloc(sizeof(int));
  *sum = *(short*)a + *(short*)b;
  return sum;
}
char* show_int(void* i)
{
  char* buf;
  buf = (char*)malloc(sizeof(int)*10/3 + 2);
  sprintf(buf, "%d", *(int*)i); /* itoa(*(int*)i, buf, 10); */
  return buf;
}

int main()
{
  short x;
  x = 12345;
  foo(plus_shorts, show_int, &x, stdout);
}
Перекуём баги на фичи!
Re[5]: В каждой шутке про ООП...
От: samius Япония http://sams-tricks.blogspot.com
Дата: 23.05.13 06:06
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, artelk, Вы писали:


К>>>Он не плюёт на LSP, а воспроизводит требования деталей. Если детали функции на субтипах — значит, и вся функция на субтипах и отвечает LSP; если детали только произвольные — значит, и вся функция произвольная.

A>>Можно пример(ы)?

К>Параметрический, вытекающий из ad-hoc


К>На С++

К>
К>template<class T> void foo(T t) { std::cout << (t+t) << std::endl; }
К>

К>Для любых подходящих типов делаем два действия
К>- T2 operator+(T,T) — как правило, перегруженный или определённый компилятором, т.е. ad-hoc
К>- ostream& operator<<(ostream&,T2) — наверняка перегруженный, т.е. ad-hoc

Я не согласен что это параметрический. Если мы разделим объявление на декларацию и объявление, то декларация будет параметрической, а объявление — ad-hoc. Чисто параметрический полиморфизм обязан работать для любых типов. А здесь — лишь для тех, для которых определены "+" и "<<".
Вобщем, и не чисто параметрический и не чисто ad-hoc. А чисто часть от того и другого.

К>То же самое на хаскелле

К>
К>foo :: (Num a, Show a) => a -> IO ()
К>foo a = putStrLn (show (a+a))
К>

К>С той разницей, что С++ генерит воплощение шаблона для каждого использованного типа, а хаскелл — единственное воплощение с двумя неявными параметрами: словарём класса Num и словарём класса Show.
Здесь чисто bounded полиморфизм. Т.к. про квантор всеобщности мы забыли при объявлении сигнатуры функции.

К>Параметрический, на субтипах

К>
К>struct INumShow // привет хаскеллу
К>{
К>  virtual INumShow* twice() = 0; // сейчас наплюём на управление памятью
К>  virtual std::string show() = 0;
К>};
К>void foo(INumShow* t) { std::cout << t->twice()->show() << std::endl; }
К>

К>В эту функцию мы можем подсунуть не любой тип, для которого определены + и <<, а только участника иерархии INumShow.
Да, и потому это не чисто параметрический, который должен принять любой тип. Это именно subtype полиморфизм.
К>Зато этих участников может быть сколько угодно, хоть из сторонней dll позаимствуем (тогда как в первом случае все типы были известны компилятору ещё до линковки).

A>>Ты о всех параметрически полиморфных функциях говоришь или только об огранниченно-полиморфных с ограничемиями вида ТипПараметра <: Тип?

A>>Если о последних, то они по своему определению всеядны по LSP.

К>Разумеется, я уже про ограниченно-полиморфные начал. Да, именно "по определению".

К>И можно заметить, что их "по определению" отличается от "по определению" ад-хок и "по определению" подлинно параметрических
С такой оговоркой часть претензий снимается, кроме разве что примера на Хаскеле. Там bounded и все тут.

К>>>Да, ещё один важный момент: для субтипов нет ограничения на количество и ассортимент типов, в отличие от ad-hoc, где количество заранее известно либо ограничено какими-то внезапными факторами (например, подгрузкой модуля, который знает, что делать с данным тэгом варианта).

A>>А для субтипов нет ограничений внезапными факторами (например, подгрузкой модуля, который знает, какие еще субтипы данного типа бывают)?

К>Предвидя вопросы, замечу: в ООП-программах встречаются места с махровым ад-хоком. Это всяческая десериализация (чтение конфигов, фабрики классов по GUID/ProgID/etc...)

Дык суть всего ООП в понимании А. Кея в терминах полиморфизма сводится к ад-хоку времени выполнения. А то что он реализован через сабтайпинг — это детали реализации.
Re[6]: В каждой шутке про ООП...
От: Кодт Россия  
Дата: 23.05.13 09:09
Оценка:
Здравствуйте, samius, Вы писали:

К>>Параметрический, вытекающий из ad-hoc


К>>На С++

К>>
К>>template<class T> void foo(T t) { std::cout << (t+t) << std::endl; }
К>>

К>>Для любых подходящих типов делаем два действия
К>>- T2 operator+(T,T) — как правило, перегруженный или определённый компилятором, т.е. ad-hoc
К>>- ostream& operator<<(ostream&,T2) — наверняка перегруженный, т.е. ad-hoc

S>Я не согласен что это параметрический. Если мы разделим объявление на декларацию и объявление, то декларация будет параметрической, а объявление — ad-hoc. Чисто параметрический полиморфизм обязан работать для любых типов. А здесь — лишь для тех, для которых определены "+" и "<<".

S>Вобщем, и не чисто параметрический и не чисто ad-hoc. А чисто часть от того и другого.

В смысле, на декларацию и объявление? Может быть, на определение?

Чисто параметрический полиморфизм — это сфероконь.
Хоть что-то же должно превратиться в конкретику, ну хотя бы, управление памятью.
Впрочем, вот пример максимально очищенного от конкретики
template<class T>  // по сути, здесь T только для контроля типов нужен - можно даже заменить на void
std::shared_ptr<T> // управление памятью абстрагировано от T, спасибо механизму shared_ptr
pop_back_if_exist(std::vector< std::shared_ptr<T> >& v) // вектору указателей всё равно, что хранить
{
  std::shared_ptr<T> f;
  if(!v.empty()) { f = v.back(); v.pop_back(); }
  return f;
}

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

К>>То же самое на хаскелле

К>>
К>>foo :: (Num a, Show a) => a -> IO ()
К>>foo a = putStrLn (show (a+a))
К>>

К>>С той разницей, что С++ генерит воплощение шаблона для каждого использованного типа, а хаскелл — единственное воплощение с двумя неявными параметрами: словарём класса Num и словарём класса Show.
S>Здесь чисто bounded полиморфизм. Т.к. про квантор всеобщности мы забыли при объявлении сигнатуры функции.

А он нам здесь нужен, квантор всеобщности? forall a вроде как подразумевается?

Опять же, можно привести примеры чистого полиморфизма — всякие там foldr (в том числе и на обобщённых списках, чтобы совсем жизнь йодом показалась).
Но, в конечном счёте, где-то будет приземление на конкретику, и из строительных кирпичиков мы построим или совсем конкретное, или ад-хок.
Я так думаю (©).

<>

К>>Предвидя вопросы, замечу: в ООП-программах встречаются места с махровым ад-хоком. Это всяческая десериализация (чтение конфигов, фабрики классов по GUID/ProgID/etc...)

S>Дык суть всего ООП в понимании А. Кея в терминах полиморфизма сводится к ад-хоку времени выполнения. А то что он реализован через сабтайпинг — это детали реализации.

Тогда хаскелл — это ООП-язык? Вот, даже слово "класс" присутствует
Перекуём баги на фичи!
Re[3]: В каждой шутке про ООП...
От: jazzer Россия Skype: enerjazzer
Дата: 23.05.13 11:04
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Начнём с самого главного: с принципа подстановки Лисков (LSP). Именно по нему проходит граница.


К>Ад-хок-полиморфизм отличается от параметрического и субтипов тем, что плюёт на LSP.

Не могу согласиться.

Во-первых, плевать или не плевать на LSP может только программист, а не конкретная техника или механизм языка.
Я уже писал на эту тему тут: http://www.rsdn.ru/forum/philosophy/4355436.1
Автор: jazzer
Дата: 25.07.11
(предлагаю прочитать, прежде чем двигаться дальше в этом посте).

Во-вторых, "обычный" полиморфизм через наследование — это просто подмножество параметрического полиморфизма с зашитым предикатом "is_base_of".
То есть следующие два куска кода ничем, кроме времени диспетчеризации (compile time/run time), не отличаются:
// классический
void f(Base& x) {}

// параметрический
template< class T>
enable_if< is_base_of<Base,T> >
f(T& x) {}

Но при параметрическом полиморфизме предикат может быть каким угодно, например, таким:
template< class T>
enable_if< is_base_of<Base1,T> || is_base_of<Base2,T> >
f(T& x) {}

или вообще
template< class T>
enable_if< quacks_as_duck<T> >
f(T& x) {}

А уже обязанность программиста — следить, чтобы типы, которые он функции подсвывает, удовлетворяли принципу Лисков.

В-третьих, ad-hoc-полиморфизм сам по себе никак не противоречит принципу Лисков, потому что представляет собой опять же просто разновидность параметрического полиморфизма. При обычном полиморфизме, когда ты добавляешь типы к множеству допустимых типов, ты ведь одновременно с этим добавляешь и какие-то операции, так? Но ведь ты можешь добавлять не только внутренние операции, но и внешние, например, придумав свой арифметический класс и правильно(!) реализовав для него арифметические операторы. Таким образом твой класс является подтипом типа аргумента оператора+.

Более того, ты можешь пойти дальше и тип, не являющийся подтипом формально, сделать таковым — я говорю здесь о traits и concept_map.

Так что LSP — это крайне широкий принцип, никак не завязанный на механизмы конкретного языка, диспетчеризацию времени исполнения или времени компиляции и т.п. Он не об этом. Он — о логической совместимости типов с неким архетипом, зашитым в предусловиях функции.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[7]: В каждой шутке про ООП...
От: samius Япония http://sams-tricks.blogspot.com
Дата: 23.05.13 12:03
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, samius, Вы писали:


К>>>Параметрический, вытекающий из ad-hoc


S>>Я не согласен что это параметрический. Если мы разделим объявление на декларацию и объявление, то декларация будет параметрической, а объявление — ad-hoc. Чисто параметрический полиморфизм обязан работать для любых типов. А здесь — лишь для тех, для которых определены "+" и "<<".

S>>Вобщем, и не чисто параметрический и не чисто ad-hoc. А чисто часть от того и другого.

К>В смысле, на декларацию и объявление? Может быть, на определение?

Верно

К>Чисто параметрический полиморфизм — это сфероконь.

В C++ — да
К>Хоть что-то же должно превратиться в конкретику, ну хотя бы, управление памятью.
В конкретику превращается все, вопрос в том, требует ли превращение в конкретику специального подхода, вот как в операторе "+".
К>Впрочем, вот пример максимально очищенного от конкретики
К>
К>template<class T>  // по сути, здесь T только для контроля типов нужен - можно даже заменить на void
К>std::shared_ptr<T> // управление памятью абстрагировано от T, спасибо механизму shared_ptr
К>pop_back_if_exist(std::vector< std::shared_ptr<T> >& v) // вектору указателей всё равно, что хранить
К>{
К>  std::shared_ptr<T> f;
К>  if(!v.empty()) { f = v.back(); v.pop_back(); }
К>  return f;
К>}
К>

К>Точнее, мы всю конкретику явно прибили гвоздями, не накладывая ограничений на собственно полиморфный тип.
Согласен

К>>>
К>>>foo :: (Num a, Show a) => a -> IO ()
К>>>

S>>Здесь чисто bounded полиморфизм. Т.к. про квантор всеобщности мы забыли при объявлении сигнатуры функции.

К>А он нам здесь нужен, квантор всеобщности? forall a вроде как подразумевается?

да, forall инстансов Num и Show. И это не то же самое что forall.

К>Опять же, можно привести примеры чистого полиморфизма — всякие там foldr (в том числе и на обобщённых списках, чтобы совсем жизнь йодом показалась).

К>Но, в конечном счёте, где-то будет приземление на конкретику, и из строительных кирпичиков мы построим или совсем конкретное, или ад-хок.
Не понимаю, какое там приземление на конкретику? Списковые функции все чисто параметрически полиморфны, не требуют никакой специализации вообще.
К>Я так думаю (©).

S>>Дык суть всего ООП в понимании А. Кея в терминах полиморфизма сводится к ад-хоку времени выполнения. А то что он реализован через сабтайпинг — это детали реализации.


К>Тогда хаскелл — это ООП-язык? Вот, даже слово "класс" присутствует

Да, хаскелл — ООП язык. Некоторые так считают. И в их числе Роман Душкин.
К сожалению, развернуть его тезисы не могу, т.к. книгу покупал в электронном виде в сервисе Bookee, который походу тихо загнулся.
Re[2]: В каждой шутке про ООП...
От: B0FEE664  
Дата: 23.05.13 16:55
Оценка: +2 :)
Здравствуйте, Sinix, Вы писали:

S> Я что-то не припомню мощных заруб на тему двоичной арифметики


big-endian VS little-endian никогда не видел?
Или там, прямой код VS дополнительный код...
И каждый день — без права на ошибку...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.