Форум: "Прочее";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];
Вниз[ООП] Хочу странного Найти похожие ветки
← →
oxffff © (2010-03-08 23:31) [40]
> Игорь Шевченко © (08.03.10 23:29) [38]
> oxffff © (08.03.10 23:20) [37]
>
>
> > Есть формальная теория рекомендую к ней обратиться.
>
>
> Есть синтаксис конкретных языков. Можно я буду к нему обращаться
> ? :)
Ради бога. Есть теория можно я буду к ней обращаться?
← →
Игорь Шевченко © (2010-03-08 23:33) [41]oxffff © (08.03.10 23:31) [40]
> Есть теория можно я буду к ней обращаться?
Ради бога. Только ты пиши, когда к теории обращаешься, чтобы было понятно, договорились ?
← →
oxffff © (2010-03-08 23:36) [42]
> Игорь Шевченко © (08.03.10 23:33) [41]
> oxffff © (08.03.10 23:31) [40]
>
>
> > Есть теория можно я буду к ней обращаться?
>
>
> Ради бога. Только ты пиши, когда к теории обращаешься, чтобы
> было понятно, договорились ?
Договорились. И?
← →
oxffff © (2010-03-08 23:40) [43]Еще немного теории
Of course, if one hides a previously public method, m, in a subclass SC of
C, then SC no longer generates objects whose type is a subtype of the objects
generated by C. Objects generated from C can respond to message m, while
those generated from SC cannot.
← →
Alkid © (2010-03-09 00:00) [44]
> oxffff © (08.03.10 23:16) [36]
> Вообще нужно говорить наверно о теории типов, а не о LSP.
>
> Так вот, то что положено в С++ это решение автора со всеми
> вытекающими.
И с какими же вытекающими? Возможность порождать подкласс, не являющийся подтипом, не противоречит абсолютно ничему. Закрытое наследование, по сути, является разновидностью композиции.
В С++ это выдерживается строго, ты не можешь приводить класс к закрытому базовому классу без применения тяжелой артиллерии в виде reinterpret_cast или C-style cast.
Так же как и в JAVA знаменитая проблема с подтипами массивов.
Можно поподробнее? Я не знаток Java, так что не в курсе проблемы.
> Читайте теорию господа.
Теория - это хорошо, но она пока не объясняет, в чем же ты усмотрел "нетипобезопасность" и прочий криминал. Нетипобезопасность, по моему пониманию, это когда ты присваиваешь переменной значение нелегального типа. Ну, есть у тебя указатель на Foo, а ты тыкаешь его в экземпляр Bar. Тогда у тебя будут все радости, типа AV, порчи памяти и так далее.
← →
Alkid © (2010-03-09 00:06) [45]
> oxffff © (08.03.10 21:16) [27]
> В Delphi есть делегирование реализации implements, если
> я правильно понял вопрос.
> В остальном я скоро приеду и у нас будет возможность посидеть
> и обсудить это. :)
Да, ты правильно понял вопрос.
А я, видимо, стал забывать Дельфи уже :)
← →
oxffff © (2010-03-09 00:22) [46]
> Alkid © (09.03.10 00:00) [44]
>
> > oxffff © (08.03.10 23:16) [36]
> > Вообще нужно говорить наверно о теории типов, а не о LSP.
>
> >
> > Так вот, то что положено в С++ это решение автора со всеми
>
> > вытекающими.
>
> И с какими же вытекающими? Возможность порождать подкласс,
> не являющийся подтипом, не противоречит абсолютно ничему.
> Закрытое наследование, по сути, является разновидностью
> композиции.
>
> В С++ это выдерживается строго, ты не можешь приводить класс
> к закрытому базовому классу без применения тяжелой артиллерии
> в виде reinterpret_cast или C-style cast.
>
Применение тяжелой артилерии(а значит и передача ответственности программисту) означает, что компилятор(среда) не может гарантировать безопасность программы самостоятельно, а это в свою очередь означает не 100% безопасность типов.
Поэтому жесткое приведение тут же как бы намекает на вопрос, а правильно ли программист спроектировал классы и отношения подтипов. И нужна ли такая возможность в языке, если она может порождать проблемы. И возможно этого можно добиться "не расширяя(засоряя)" язык посредством примитивных базовых конструкций.
>
> Так же как и в JAVA знаменитая проблема с подтипами массивов.
>
>
> Можно поподробнее? Я не знаток Java, так что не в курсе
> проблемы.
>
>
JAVA правило для массивов.
B[] является подтипом A[], если B является подтипом A.
Что приводит к тому, что в массив фруктов можно добавить овощи.
> > Читайте теорию господа.
>
> Теория - это хорошо, но она пока не объясняет, в чем же
> ты усмотрел "нетипобезопасность" и прочий криминал. Нетипобезопасность,
> по моему пониманию, это когда ты присваиваешь переменной
> значение нелегального типа. Ну, есть у тебя указатель на
> Foo, а ты тыкаешь его в экземпляр Bar. Тогда у тебя будут
> все радости, типа AV, порчи памяти и так далее.
см. выше+
Every value generated in a program is associatedwith a type, either explicitly
or implicitly. In a strongly typed language, the language implementation
is required to provide a type checker that ensures that no type errors will occur
at run time.
← →
Игорь Шевченко © (2010-03-09 00:25) [47]oxffff © (09.03.10 00:22) [46]
> Every value generated in a program is associatedwith a type,
> either explicitly
> or implicitly. In a strongly typed language, the language
> implementation
> is required to provide a type checker that ensures that
> no type errors will occur
> at run time.
Если тебя не затруднит, ты по-русски сразу пиши, а ?
Задолбало уже.
← →
oxffff © (2010-03-09 00:32) [48]
> Игорь Шевченко © (09.03.10 00:25) [47]
> oxffff © (09.03.10 00:22) [46]
>
>
> > Every value generated in a program is associatedwith a
> type,
> > either explicitly
> > or implicitly. In a strongly typed language, the language
>
> > implementation
> > is required to provide a type checker that ensures that
>
> > no type errors will occur
> > at run time.
>
>
> Если тебя не затруднит, ты по-русски сразу пиши, а ?
> Задолбало уже.
Все я спать пошел. :)
← →
Германн © (2010-03-09 00:44) [49]
> Игорь Шевченко © (09.03.10 00:25) [47]
Вроде нет проблем с переводом. Всё с первого взгляда понятно.
Или я "не в теме"?
← →
Alkid © (2010-03-09 09:53) [50]
> oxffff © (09.03.10 00:22) [46]
> Применение тяжелой артилерии(а значит и передача ответственности
> программисту) означает, что компилятор(среда) не может гарантировать
> безопасность программы самостоятельно, а это в свою очередь
> означает не 100% безопасность типов.
Безусловно. Собственно, эти типы приведения нужны *только* для низкоуровневой работы с памятью. За создание закрытого наследования и приведения его потом к приватной базе через reinterpret_cast надо расстреливать через повешение. При нормальном проектировании такого быть не должно, что не отменяет допустимость закрытого наследования.
> Every value generated in a program is associatedwith a type,
> either explicitly
> or implicitly. In a strongly typed language, the language
> implementation
> is required to provide a type checker that ensures that
> no type errors will occur
> at run time.
Ну вот и поясни мне, как закрытое наследование порождает "error at run time", а то я пока не понимаю этого.
← →
oxffff © (2010-03-09 10:11) [51]
> Ну вот и поясни мне, как закрытое наследование порождает
> "error at run time", а то я пока не понимаю этого.
Очень просто. Есть класс B, который наследует приватно от А, скрывая интерфейс А, и выставляя некий свой другой. Что означает, что изменение значений закрытой части в B, контролирует B, но не внешнее окружение. А это в свою очередь означает, что эти закрытые члены могут принимать некие определенные значения(их домен значений в B, например подмножество всех допустимых значений в А), а также все отношения между этимим полями должны быть определенными и могут иметь предназначение отличное от их предназначения в А. Поэтому если B трактовать как A(отношение подтипа), по мы нарушает абстракцию B, Что могут вызвать ошибки времени исполнения, в случае если значения вышли из домена значений допустимых в B(например индекс в неком расделенном массиве). Надеюсь я понятно объяснил. :)
← →
oxffff © (2010-03-09 10:14) [52]
> Поэтому если B трактовать как A(отношение подтипа), по
> мы нарушает абстракцию B, Что могут вызвать ошибки времени
> исполнения, в случае если значения вышли из домена значений
> допустимых в B(например индекс в неком расделенном массиве).
> Надеюсь я понятно объяснил. :)
например для А допустимы индексы от 1 до 100.
Для B допустимы индексы от 5 до 87.
Значение индекса вне [5,87] будет некорректным в B, что приведет к ошибке в его работе и значит и ошибки Run-time. :)
← →
Alkid © (2010-03-09 10:46) [53]
> oxffff © (09.03.10 10:11) [51]
> oxffff © (09.03.10 10:14) [52]
Не, я не понял, что ты имеешь в виду. Закрытое наследование не порождаем подтипа. Т.е.:
class A { };
class B : private A {};
...
A* a = new B(); // Ошибка компиляции!
Это означает, что ты не можешь передать B туда, где применим А, принцип подстановки не работает. Пользователь класса B не знает о том, что тот унаследован от A, это является исключительно деталью реализации.
В общем, жду примера, в котором без применения всяких дурных кастов ты получишь нетипобезопасную программу. Т.е. компилирующуюся, но падающую в run-time от ошибки типов.
← →
jack128_ (2010-03-09 10:52) [54]
> Некто (08.03.10 13:27)
тут обсуждение в какие то непнятные теоретические дебри и особенности cpp, давайте ближе к телу вопроса.
мя в предложенной схеме смущают два момента:
1) весь публичный интерфейс - полиморфный.
2) отсутствие protected (в виду отсутствия наследования классов)
в качестве примера шаблонный метод реализуем:
TBase = class
protected
procedure DoStep1(); virtual;
procedure DoStep2(); virtual;
procedure DoStep3(); virtual;
public
procedure DoWork(); // вызывает последовательно DoStep1/DoStep2/DoStep3
end;
TChild1 = class(TBase)
protected
procedure DoStep1(); override;
procedure DoStep2(); override;
procedure DoStep3(); override;
end;
TChild2 = class(TBase)
protected
procedure DoStep1(); override;
procedure DoStep2(); override;
procedure DoStep3(); override;
end;
по твоей схеме эту иерархию мона преобразовать так:
IBase = interface
procedure DoStep1();
procedure DoStep2();
procedure DoStep3();
end;
procedure DoWork(base: IBase);
begin
base.DoStep1();
base.DoStep2();
base.DoStep3();
end;
но тогда отдельные шаги передут в публичный интерфейс и станут доступны каждому встречному поперечному.
либо просто объявить
IWorker = interface
procedure DoWork();
end
но тогда теряется шаблонность. Как быть??
← →
oxffff © (2010-03-09 10:55) [55]
> Alkid © (09.03.10 10:46) [53]
>
> > oxffff © (09.03.10 10:11) [51]
> > oxffff © (09.03.10 10:14) [52]
>
> Не, я не понял, что ты имеешь в виду. Закрытое наследование
> не порождаем подтипа. Т.е.:
>
> class A { };
> class B : private A {};
> ...
> A* a = new B(); // Ошибка компиляции!
>
> Это означает, что ты не можешь передать B туда, где применим
> А, принцип подстановки не работает. Пользователь класса
> B не знает о том, что тот унаследован от A, это является
> исключительно деталью реализации.
>
> В общем, жду примера, в котором без применения всяких дурных
> кастов ты получишь нетипобезопасную программу. Т.е. компилирующуюся,
> но падающую в run-time от ошибки типов.
Ты определись что ты хочешь?
Я написал что применение закрытого наследования при сохранении отношений подтипа для подклассов или использования cast"ов является небезопасным.
← →
Alkid © (2010-03-09 11:06) [56]
> oxffff © (09.03.10 10:55) [55]
А я писал, что подтип и подкласс - не синонимы, что допустимо порождать подкласс, не являющийся подтипом, и что за касты расстреливать надо на месте :)
Смотри [44], откуда все началось.
← →
Alkid © (2010-03-09 11:09) [57]
> jack128_ (09.03.10 10:52) [54]
ISteps = interface
procedure DoStep1();
procedure DoStep2();
procedure DoStep3();
end;
IWorker = interface
procedure DoWork();
end
TWorker = interface(IWokrer)
FSteps : IWorker; // Либо инжектируется в конструктор, либо создается там же.
end;
procedure TWorker.DoWork(base: IBase);
begin
FSteps.DoStep1();
FSteps.DoStep2();
FSteps.DoStep3();
end;
Шаблонность сохраняется.
← →
Alkid © (2010-03-09 11:10) [58]Тьфу, поправочка:
TWorker = interface(IWokrer)
FSteps : ISteps; // Либо инжектируется в конструктор, либо создается там же.
end;
← →
jack128_ (2010-03-09 11:15) [59]
> Шаблонность сохраняется.
ну как же она сохраняется то, если мы мы работаем через интерфейс IWorker?
← →
oxffff © (2010-03-09 11:16) [60]
> Alkid © (09.03.10 11:06) [56]
>
> > oxffff © (09.03.10 10:55) [55]
>
> А я писал, что подтип и подкласс - не синонимы, что допустимо
> порождать подкласс, не являющийся подтипом, и что за касты
> расстреливать надо на месте :)
>
> Смотри [44], откуда все началось.
Что смотреть?
Я еще раньше написал [28], что изменение видимости в сторону уменьшения пагубно влияет на отношении подтипов при сохранении отношения формально подклассов.
Началось все с [28]. Где речь шла о наделении языка такой возможностью, при сохранении остальной части.
← →
Alkid © (2010-03-09 11:21) [61]
> jack128_ (09.03.10 11:15) [59]
Тогда поясни, что ты имеешь в виду под шаблонностью. Я думал, что ты под шаблоном понимаешь метод DoWork, который оперирует методами DoStepX(), реализация которых может быть подменена в наследниках. Так?
Здесь имеем тоже самое, только реализация подменяется не путем наследования, а путем инжектирования другой реализации ISteps. Это, кстати, вполне себе обычный паттерн, который применяется и без залезания в те дебри, в которые я вознамерился тут залезть :)
← →
Alkid © (2010-03-09 11:24) [62]
> oxffff © (09.03.10 11:16) [60]
Понятно, имеется некий мисандерстендинг :) Там ты отвечал на пост Игоря :)
Короче, я хочу странного, но не настолько, что бы сохранять отношение подтипа с закрытым наследованием :) Считаю, что этот вопрос исчерпан :)
← →
jack128_ (2010-03-09 11:27) [63]
> Я думал, что ты под шаблоном понимаешь метод DoWork, который
> оперирует методами DoStepX(), реализация которых может быть
> подменена в наследниках. Так?
именно + то, что этот метод НЕвиртуален. ТО есть мы фиксируем реализацию этого метода, не даем никому её подменить. В твоем же коде - я всегда могу написать свой реализатор IWorker который будет делать все что хочешь, только не вызывать шаги.
собственно я ж написал как эту проблему избежать, нужно просто вызов шагов загнать в обычную процедуру (см [54])
← →
Alkid © (2010-03-09 11:30) [64]
> jack128_ (09.03.10 11:27) [63]
А, ты об этом. Ну да, можно и так сделать. Это не влияет на замену наследования делегирования.
← →
jack128_ (2010-03-09 11:32) [65]у мя в [54] еще второй пункт есть. по поводу того, что в исходном коде DoStepX() - доступны только подклассам - а в твоем варианте - они доступны кому угодно
← →
Игорь Шевченко © (2010-03-09 12:25) [66]Не удержусь:
"ОО-языки упрощают абстракцию, возможно, даже слишком ее упрощают. Они поддерживают
создание структур с большим количеством связующего кода и сложными уровнями.
Это может оказаться полезным в случае, если предметная область является
действительно сложной и требует множества абстракций, и вместе с тем такой
подход может обернуться неприятностями, если программисты реализуют простые
вещи сложными способами, просто потому что им известны эти способы и они умеют
ими пользоваться.
Все ОО-языки несколько сколнны "втягивать" программистов в ловушку избыточной
иерархии. Чрезмерное количество уровней разрушает прозрачность: крайне
затрудняется их просмотр и анализ ментальной модели, которую по существу
реализует код. Всецело нарушаются правила простоты, ясности и прозрачности,
а в результате код наполняется скрытыми ошибкми и создает постоянные проблемы
при сопровождении.
Данная тенденция, вероятно, усугубляется тем, что множество курсов по
программированию преподают громоздкую иерархию как способ удовлетворения
правила представления. С этой точки зрения множество классов приравнивается
к внедрению знаний в данные. Проблема данного подхода заключается в том, что
слишком часто "развитые данные" в связующих уровнях фактически не относятся
у какому-либо естественному объекту в области действия программы -
они предназначены только для связующего уровня.
Одной из причин того, что ОО-языки преуспели в большинстве характерных для них
предметных областей (GUI-интерфейсы, моделирование, графические средства),
возможно, является то, что в этих областях относительно трудно неправильно
определить онтологию типов. Например, в GUI-интерфейсах и графических средствах
присутствует довольно естественное соотвествие между манипулируемыми
визуальными объектами и классами. Если выясняется, что создается большое
количество классов, которые не имеют очевидного соответствия с тем, что
происходит на экране, то, соотвественно, легко заметить, что связующий уровень
стал слишком большим.
"
Эрик Реймонд, "Искусство программирования для Unix"
← →
Alkid © (2010-03-09 12:37) [67]
> Игорь Шевченко © (09.03.10 12:25) [66]
и-и-и? ;) Какая связь с обсуждаемым вопросом?
← →
Игорь Шевченко © (2010-03-09 13:11) [68]Alkid © (09.03.10 12:37) [67]
Скорее, с развитием и ответвлениями обсуждаемого вопроса.
← →
Alkid © (2010-03-09 13:35) [69]
> Игорь Шевченко © (09.03.10 13:11) [68]
А, понятно. Просто то, что я предлагаю, на количество уровней абстракции не влияет. Те же яйца, вид сбоку, если в двух словах :)
← →
oxffff © (2010-03-09 14:34) [70]
> Alkid © (09.03.10 11:24) [62]
>
> > oxffff © (09.03.10 11:16) [60]
>
> Понятно, имеется некий мисандерстендинг :) Там ты отвечал
> на пост Игоря :)
> Короче, я хочу странного, но не настолько, что бы сохранять
> отношение подтипа с закрытым наследованием :) Считаю, что
> этот вопрос исчерпан :)
Отношение подтипа с закрытым наследованием можно сохранить, если выдать свой собственный интерфейс идентичный необходимому типу(например супертипу)(однако возникнет проблема бинарной совместимости, поскольку смещения поменяются. Но если изменить способ обращения(исполнения кода, например интерпретатор) без привязки к смещению, то это можно решить. Более того есть такие реализации без "вертикальной сабтипизациии".
← →
Piter © (2010-03-09 14:54) [71]Игорь Шевченко © (09.03.10 12:25) [66]
Эрик Реймонд, "Искусство программирования для Unix"
Игорь, я так понимаю вы в настоящее время интересуетесь программингом в сторону *nix платформ.
Если не сложно - посоветуйте что прочитали, что думаете, какие книжки особо понравились, какой нужен уровень для их корректного прочтения?
Еще вопрос - какие языки, среды, технологии используете для программинга под *nix? Вас интересует именно *nix как таковой или в сфере кросс-платформенных приложений? На чем остановились?
P.S. Эрик C. Реймонд - Искусство программирования для Unix, это я так понимаю как раз ликбез-обзор по существующим технологиям?
← →
Alkid © (2010-03-09 15:02) [72]
> oxffff © (09.03.10 14:34) [70]
Интерфейсы спасут отца русской демократии от бинарной совместимости. С другой стороны, зачем сохранять отношения подтипа, если закрытое наследование для того и сделано, что бы это отношение ликвидировать? :)
← →
oxffff © (2010-03-09 15:22) [73]
> Alkid © (09.03.10 15:02) [72]
>
> > oxffff © (09.03.10 14:34) [70]
>
> Интерфейсы спасут отца русской демократии от бинарной совместимости.
> С другой стороны, зачем сохранять отношения подтипа, если
> закрытое наследование для того и сделано, что бы это отношение
> ликвидировать? :)
От бинарной несовместимости? :)
Вот вот и я думаю, что в твоем вопросе [0] интерфейсы спасут тебя. :)
А Delphi impelements наделит тебя необходимой силой воина со сложностью. :)
Закрытое наследование является формой агрегации реализации. Отношение подтипа можно сохранить например для того, чтобы внести в реализацию некие изменения, полностью заменив или частично. Однако получается, что привычная VMT уже не нужна. А приобретает некую форму разрешения как для мультиметода в run time.
← →
GDI+ (2010-03-09 19:33) [74]
> Некто (08.03.10 13:27)
>
> При спорах вида "С++ vs X", где Х - любой объектно-ориентированный
> ЯП, поддерживающий единичное наследование, неизбежно возникает
> ответвление спора на тему "множественное наследование vs.
> единичное наследование". Защитники МН упирают на бОльшую
> гибкость и возможности, которые дает МН, противники - на
> то, что МН усложняет реализацию языка, сам язык и что МН
> вообще не нужно.
Множественное наследование необходимо. Без него никак. Но в нормальных языках множественное наследование реализовано через интерфейсы.
А множественное наследование реализации, а не декларации это изврат и нигде не используется.
← →
GDI+ (2010-03-09 19:34) [75]
> Игорь Шевченко © (08.03.10 13:51) [7]
>
> Есть множественное наследование интерфейса и множественное
> наследование реализации. Хорошо и то, и другое.
Плохо. Хотя, если цель обфускация кода, то хорошо.
← →
Игорь Шевченко © (2010-03-09 19:42) [76]GDI+ (09.03.10 19:33) [74]
> А множественное наследование реализации, а не декларации
> это изврат и нигде не используется.
Кругозор надо расширять, не будешь ерундой болтать
← →
Alkid © (2010-03-09 19:50) [77]
> GDI+ (09.03.10 19:33) [74]
> Множественное наследование необходимо. Без него никак. Но
> в нормальных языках множественное наследование реализовано
> через интерфейсы.
>
> А множественное наследование реализации, а не декларации
> это изврат и нигде не используется.
Аргументируй.
Кстати, насчет "нигде не используется" ты не прав. В stl очень даже используется в виде trait-классов. На прошлой работе применял множественное наследования для реализации mixin-style.
Так что хочу услышать аргументированное изложение недостатков множественного наследования.
← →
GrayFace © (2010-03-11 02:41) [78]oxffff © (08.03.10 21:34) [28]
Этой возможности быть и не должно. :)
Поскольку, если B является подклассом A, то B является подтипом A.
Если позволить менять видимость, то тогда B не будет являться подтипом A.
Поскольку B не может выступить в качестве А
(нарушение типобезопасности, то есть язык будет являться небезопасным)
Лучше было бы, если бы была. Это очень полезно для published свойств, иногда полезно для public. При приведении к A эти методы можно будет вызвать. Т.е. прятанье должно быть чисто внешнее.
А то, как сейчас, плодить TCustom*, вписывать в published свойства под все версии Delphi - это не дело.
Спасибо за implements!
← →
oxffff © (2010-03-11 08:40) [79]
> Лучше было бы, если бы была. Это очень полезно для published
> свойств, иногда полезно для public. При приведении к A эти
> методы можно будет вызвать. Т.е. прятанье должно быть чисто
> внешнее.
> А то, как сейчас, плодить TCustom*, вписывать в published
> свойства под все версии Delphi - это не дело.
Это всего лишь реализация VCL. К формальной теории отношения не имеет.
← →
GrayFace © (2010-03-12 15:10) [80]oxffff © (11.03.10 8:40) [79]
Это всего лишь реализация VCL. К формальной теории отношения не имеет.
При чем тут реализация VCL? Это свойство языка, которое было бы полезным.
Речь была о
Классические пуристы возражают против наследников, например, от TList. Их аргументы таковы, что наследнику в большинстве случаев не нужны методы предка Exchange, Move, и т.д.
Нету в Delphi возможность понизить область видимости - ну такой язык.
С этим данное "частичное" понижение видимости отлично бы справилось.
Страницы: 1 2 3 вся ветка
Форум: "Прочее";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];
Память: 0.66 MB
Время: 0.063 c