Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2007.04.22;
Скачать: [xml.tar.bz2];

Вниз

Вот завел себе блог   Найти похожие ветки 

 
Суслик ©   (2007-03-05 01:10) [0]

Здравствуйте.

Сегодня я завел себе блог http://timokhov.blogspot.com/
Как таковой мне лично он не нужен :) Я его завел для того, чтобы доносить народу новости о Delphi 2007, которая выйдет очень скоро.

Если кому интересно, то можете читать блог и оставлять комменты (вот я оторвусь на модерировании :)).

Я планирую писать что-то каждый день. Писать есть о чем.


 
Германн ©   (2007-03-05 03:04) [1]


> Я планирую писать что-то каждый день. Писать есть о чем.
>

В добрый путь! (Только не возгордись слишком:)


 
Суслик ©   (2007-03-05 03:07) [2]


> Германн ©   (05.03.07 03:04) [1]
> > Я планирую писать что-то каждый день. Писать есть о чем.
> В добрый путь! (Только не возгордись слишком:)


И как тебе в голову могло прийти такое пожелание? :(


 
Германн ©   (2007-03-05 03:30) [3]


> И как тебе в голову могло прийти такое пожелание? :(
>

Меня смутило то, что это уже вторая твоя ветка по данному вопросу за небольшой период времени. :( Ведь http://delphimaster.net/view/15-1173008259/ ещё даже не ушла с первой страницы!


 
KSergey ©   (2007-03-05 10:39) [4]

Прикольно, людям есть что писать каждый день...


 
Суслик ©   (2007-03-06 15:26) [5]

Что вы знаете про FastMM? Хороший и бесплатный прибамбас к Дельфи, способный сильно повысить качество создаваемых программ.

Я попытался его описать на минимальном уровне, достаточном для начала использования.

http://timokhov.blogspot.com/2007/03/delphi-2007-iii-fastmm.html

Замечания welcome.


 
Плохиш ©   (2007-03-06 15:32) [6]

Незачёт!
Темы разведения сусликов и секса не раскрыты :-(


 
Ega23 ©   (2007-03-06 15:34) [7]

Дима!
Хватит дизайн менять по 5 раз на дню.


 
Суслик ©   (2007-03-06 16:07) [8]


>  [7] Ega23 ©   (06.03.07 15:34)
> Дима!
> Хватит дизайн менять по 5 раз на дню.

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


 
Dok_3D ©   (2007-03-07 09:57) [9]

2 KSergey ©   (05.03.07 10:39) [4]
>>Прикольно, людям есть что писать каждый день...

Гораздо прикольней, что теперь людям есть что читать каждый день :))


 
Суслик ©   (2007-03-07 10:24) [10]

Я кстате наботал хороший блог. У меня в блоге есть ссылка.
Весьма интересно. Я этого норвежца знаю - весьма квалифицированный программист: ерунды писать не будет.


 
xayam ©   (2007-03-09 11:53) [11]


> Суслик ©  

кстати раз ты тестируешь D2007, у нее есть такой баг http://delphimaster.net/view/15-1173008259/  ? На турбе и 2006 есть.


 
jack128 ©   (2007-03-09 13:50) [12]

Дим, а будет подправлен баг с хелперами такого содержания:
Хелпер - предок

unit Unit3;

interface

uses
 Classes;

type
 TStringsHelper = class helper for TStrings
 public
   procedure DoWork;
 end;

implementation

procedure TStringsHelper.DoWork;
begin
 //
end;

end.


Хелпер-потомок, добавляет overload метод
unit Unit4;

interface

uses
 Classes, Unit3;

type
 TStringsHelper = class helper for TStrings
 public
   procedure DoWork(I: Integer); overload;
 end;

implementation

procedure TStringsHelper.DoWork(I: Integer);
begin
 //
end;

end.


используем:

unit Unit2;
uses
 Unit3;

procedure TForm2.Button1Click(Sender: TObject);
begin
 Memo1.Lines.DoWork; // [Pascal Error] Unit2.pas(30): E2250 There is no overloaded version of "DoWork" that can be called with these arguments
end;


То есть потомок скрывает метод предка, не смотря на дерективу overload


 
Игорь Шевченко ©   (2007-03-09 15:45) [13]


> используем:
>
> unit Unit2;
> uses
>  Unit3;
>
> procedure TForm2.Button1Click(Sender: TObject);
> begin
>  Memo1.Lines.DoWork; // [Pascal Error] Unit2.pas(30): E2250
> There is no overloaded version of "DoWork" that can be called
> with these arguments
> end;


Я сильно извиняюсь, а если unit4 включить в uses ?


 
Суслик ©   (2007-03-09 15:57) [14]


> Я сильно извиняюсь, а если unit4 включить в uses ?

вот он опыт! а я и не заметил, что unit4 отсутствует


 
Ega23 ©   (2007-03-09 16:00) [15]

Я сильно извиняюсь, но что это за зверь:
TStringsHelper = class helper for TStrings????

З.Ы. смотрел в хелпе - не понял. Delphi 7.


 
Kolan ©   (2007-03-09 16:02) [16]

> не понял. Delphi 7

Шутишь, да?

от BDS почитай справку "class helpers"


 
Джо ©   (2007-03-09 16:02) [17]

> [15] Ega23 ©   (09.03.07 16:00)
> Я сильно извиняюсь, но что это за зверь:
> TStringsHelper = class helper for TStrings????
>
> З.Ы. смотрел в хелпе - не понял. Delphi 7.

Это нужно смотреть в хелпе к 2006 & 2007 :)


 
Игорь Шевченко ©   (2007-03-09 16:06) [18]

Джо ©   (09.03.07 16:02) [17]

Можно прочитать нашу статью на Королевстве Delphi про Delphi 2005, там, где эти helper"ы появились.

Ega23 ©   (09.03.07 16:00) [15]

Helper - это конструкция языка, позволяющая добавлять к классу поведение, не меняя его объявления. Сделано при реализации Delphi для .Net, в первую очередь.


 
Ega23 ©   (2007-03-09 16:10) [19]


> Helper - это конструкция языка, позволяющая добавлять к
> классу поведение, не меняя его объявления. Сделано при реализации
> Delphi для .Net, в первую очередь.
>


Понял.
С .Net дел не иммел. Просто увидел такую конструкцию - и стало страшно интересно, чего я не знаю.
Всем спасибо!


 
Джо ©   (2007-03-09 16:28) [20]

> [19] Ega23 ©   (09.03.07 16:10)

> С .Net дел не иммел.

Это применимо и к версии языка для Win32.


 
Игорь Шевченко ©   (2007-03-09 16:33) [21]

Джо ©   (09.03.07 16:28) [20]


> Это применимо и к версии языка для Win32.


Это да, применимо. Только не всегда можно понять, когда имеет смысл применять такую конструкцию в реальной жизни


 
Суслик ©   (2007-03-09 16:37) [22]


> Это да, применимо. Только не всегда можно понять, когда
> имеет смысл применять такую конструкцию в реальной жизни

согласен.
я вообще не очень понимаю семантическую нагрузку, возложенную на хелперы. было бы очень здоров, если бы:
1. дока по хелперам была лучше.
2. сам кодгир показал мастер-класс применения хелперов где-то у себя в коде. пока, насколько я знаю, примеров нет.


 
jack128 ©   (2007-03-09 16:43) [23]

Суслик ©   (09.03.07 15:57) [14]
> Я сильно извиняюсь, а если unit4 включить в uses ?

вот он опыт! а я и не заметил, что unit4 отсутствует

то же самое.


 
oxffff ©   (2007-03-09 16:47) [24]


> согласен.
> я вообще не очень понимаю семантическую нагрузку, возложенную
> на хелперы. было бы очень здоров, если бы:
> 1. дока по хелперам была лучше.
> 2. сам кодгир показал мастер-класс применения хелперов где-
> то у себя в коде. пока, насколько я знаю, примеров нет.


Скорее всего смысл в том, что для некоторых классов имеет место быть набор процедур и функций, которые являются вспомогательными и вносить их определение класса является семантической ошибкой.

Но поскольку их  можно/нужно сгруппировать. поэтому и придумали концепцию helperов (аля подпространства имен для класса) .  
Imho.


 
Джо ©   (2007-03-09 16:47) [25]

> [21] Игорь Шевченко ©   (09.03.07 16:33)
> Джо ©   (09.03.07 16:28) [20]
>
>
> > Это применимо и к версии языка для Win32.
>
>
> Это да, применимо. Только не всегда можно понять, когда
> имеет смысл применять такую конструкцию в реальной жизни

Я, честно говоря, так ни разу и не использовал, тоже применения не нашел :) Ну, если бы еще были закрытые для наследования классы, то тогда, в качестве костыля, может и пригодилось бы. А так — тоже не понимаю, зачем вносить в код лишнюю путаницу.
Недавно писал SaveToStream одного вреднего класса. Вначале наделал хелперов к TStream вроде WriteString и т.п. Затем подумал... и убрал :) Не знаю, может и зря убрал. В общем, я еще открыт для выслушивания мнений по этой теме :)


 
oldman ©   (2007-03-09 16:47) [26]


> Суслик ©   (06.03.07 15:26) [5]
> Что вы знаете про FastMM? Хороший и бесплатный прибамбас
> к Дельфи, способный сильно повысить качество создаваемых
> программ.


Улыбнуло...

Имхо, лучший прибамбас к Дельфи, действительно способный повысить качество создаваемых программ - это программист!!!
:)))


 
Суслик ©   (2007-03-09 16:49) [27]


>  [26] oldman ©   (09.03.07 16:47)

не нравится - не читай. а прибамбас действительно полезен изрядно.


 
oxffff ©   (2007-03-09 16:51) [28]

в добавлении к  oxffff ©   (09.03.07 16:47) [24]

Хочу заметить. Что при определении виртуальной функции в helper требуется наличие методов Iunknown. При добавлении их. Вызов не работает.
ASM код мы уже разбирали летом.
Кстати есть вопрос по этому поводу на qc.


 
oldman ©   (2007-03-09 16:52) [29]


> Суслик ©   (09.03.07 16:49) [27]


Я же написал - "улыбнуло"...
Хамить-то зачем?
А то ведь "хамить не надо по телефону" Варенуху знаешь куда привело? :)


 
jack128 ©   (2007-03-09 16:53) [30]

jack128 ©   (09.03.07 16:43) [23]
то же самое.

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


 
Суслик ©   (2007-03-09 16:57) [31]

могу пример привести, где хелперы могут быть полезны.

есть такая билиотека nativexml - некий xml парсер. хорош тем, что на дельфи, в исходниках и ни от кого не зависишь - парсер всегда с тобой.

так вот, данная библиотека обладает весьма мерзким (имхо) и невнятным интерфейсом. одним словом не все мне в ней нравится.

допустим я хочу написать метод, который более удовлетворяет моим представлениям об удобстве использования данной библиотеки.

какие есть пути? можно написать потомка. но! что с ним дальше делать? ведь сама баблиотека ничего о потомке не знает. Например, если я напишу TXmlNodeEx (потомок от TXmlNode - класс, соответствующий узлу в nativexml), то что мне с ним делать дальше? сама библиотека как плодила TXmlNode, так и будет это продолжать делать.

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


 
jack128 ©   (2007-03-09 16:58) [32]

Джо ©   (09.03.07 16:47) [25]
Вначале наделал хелперов к TStream вроде WriteString и т.п. Затем подумал... и убрал :)

И чем заменил?  Набором процедур аля:

procedure Stream_WriteString(AStream: TStream; const S: string);
function Stream_ReadString(AStream: TStream): string;

и чем это лудше хелперов??
Сравни:

procedure TSomeObject.ReadFromStream(Stream: TStream); {override}
begin
 inherited;
 SomeStrProp := Stream_ReadString(Stream);
end;

procedure TSomeObject.ReadFromStream(Stream: TStream); {override}
begin
 inherited;
 SomeStrProp := Stream.ReadString;
end;
Помоему второй вариант гараздо проще для восприятия.


 
jack128 ©   (2007-03-09 16:59) [33]

Суслик ©   (09.03.07 16:57) [31]
выходом может быть написание хелпера. это единственное место, где я этими хелперами пока пользуюсь.


Таким местом может быть любая сторонняя библиотека. В первую очередь - VCL


 
Суслик ©   (2007-03-09 17:00) [34]


>  [30] jack128 ©   (09.03.07 16:53)
> jack128 ©   (09.03.07 16:43) [23]
> то же самое.
> вообще - для доступа к методам хелпера-предка не обязательно
> добавлять его юнит в uses/ Достаточно добавить туда хотя
> бы один из модулей, где объявлен хелпер-потомок.

правило простое - используется 0 или 1 хелпер, который ближе по скопу.

будет ближе предок, будет предок использовать. будет потомок - значит потомок.


>  [29] oldman ©   (09.03.07 16:52)

ладно, не обращай внимания :) это я так - подумал, что издеваешься :)


 
Суслик ©   (2007-03-09 17:01) [35]


> [33] jack128 ©   (09.03.07 16:59)
> Таким местом может быть любая сторонняя библиотека. В первую
> очередь - VCL

Твоя правда.


 
Джо ©   (2007-03-09 17:01) [36]

> [32] jack128 ©   (09.03.07 16:58)
> Джо ©   (09.03.07 16:47) [25]
> Вначале наделал хелперов к TStream вроде WriteString и т.п.
> Затем подумал... и убрал :)
> И чем заменил?

Да просто наделал в своем «вредном классе» приватных методов WriteString, WriteSomething и все...


> и чем это лудше хелперов??

Черт его знает. (Не)здоровый консерватизм, в первую очередь. Как-то оно непривычно :)


 
Суслик ©   (2007-03-09 17:02) [37]


>  [36] Джо ©   (09.03.07 17:01)
> Черт его знает. (Не)здоровый консерватизм, в первую очередь.
> Как-то оно непривычно :)


и правильно делаешь :) они пока доку нормальную не напишут к хелперам с указанием всех особенностей их использования я их широко использовать не буду.


 
Игорь Шевченко ©   (2007-03-09 17:04) [38]

jack128 ©   (09.03.07 16:53) [30]

Какие предки и потомки у helper"ов ? Каждый helper является равноправным.

в help написано -

"You can define and associate multiple class helpers with a single class type. However, only zero or one class helper applies in any specific location in source code. The class helper defined in the nearest scope will apply"

все прекрасно работает:

unit helper1;

interface
uses
Classes;

type
 TStringsHelper = class helper for TStrings
 public
   procedure DoWork;
 end;

implementation

{ TStringsHelper }

procedure TStringsHelper.DoWork;
begin
 //
end;

end.


unit Helper2;

interface
uses
Classes, Helper1;

type
TStringsHelper2 = class helper for TStrings
public
  procedure DoWork(I: Integer);
end;

implementation

{ TStringsHelper }

procedure TStringsHelper2.DoWork(I: Integer);
begin
 //
end;

end.


использование:

implementation
uses
 helper2, helper1;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 Memo1.Lines.DoWork;
end;

end.


или

implementation
uses
 helper1, helper2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 Memo1.Lines.DoWork(1);
end;

end.


Helper"ы не знают друг про друга, как классы в иерархии, поэтому overload к ним вряд ли применим в твоем случае.

Вот такой код еще работает:

unit Helper3;

interface
uses
 Classes;

type
 TStringsHelper = class helper for TStrings
 public
   procedure DoWork; overload;
   procedure DoWork (I : Integer); overload;
 end;

implementation

{ TStringsHelper }

procedure TStringsHelper.DoWork;
begin
 //
end;

procedure TStringsHelper.DoWork(I: Integer);
begin
 //
end;

end.


Использование:

implementation
uses
 helper1, helper2, helper3;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 Memo1.Lines.DoWork(1);
 Memo1.Lines.DoWork;
end;

end.


 
oxffff ©   (2007-03-09 17:04) [39]

Есть еще вариант

TXmlNodeAdapter=class
public
construcor create(Node:TXmlNode);
end;


 
Игорь Шевченко ©   (2007-03-09 17:06) [40]

Кстати, пониманию исходного кода эти хелперы не способствуют, а вредят.


 
jack128 ©   (2007-03-09 17:06) [41]

Суслик ©   (09.03.07 17:00) [34]
правило простое - используется 0 или 1 хелпер, который ближе по скопу.


БЛИН!!!! Я облажался, когда пример писал.

Хелпер-потомок, добавляет overload метод
unit Unit4;

interface

uses
Classes, Unit3;

type
TStringsHelper = class helper (Unit3.TStringsHelper) for TStrings
public
  procedure DoWork(I: Integer); overload;
end;

implementation

procedure TStringsHelper.DoWork(I: Integer);
begin
//
end;

end.


То есть потомок скрывает метод предка, хотя в потомке метолдж объявлен как overload


 
jack128 ©   (2007-03-09 17:07) [42]

Игорь Шевченко ©   (09.03.07 17:06) [40]
Кстати, пониманию исходного кода эти хелперы не способствуют, а вредят.

почему?


 
Суслик ©   (2007-03-09 17:07) [43]


>  [38] Игорь Шевченко ©   (09.03.07 17:04)

вообще-то хелперы и наследовать можно


 
Суслик ©   (2007-03-09 17:08) [44]


> [42] jack128 ©   (09.03.07 17:07)
> Игорь Шевченко ©   (09.03.07 17:06) [40]
> Кстати, пониманию исходного кода эти хелперы не способствуют,
> а вредят.
> почему?


Игорь из партии консерваторов :)

Хотя я скорее соглашусь с ним - использовать данную конструкцию на регулярной основе не нужно. Только как исключительный случай.


 
Суслик ©   (2007-03-09 17:09) [45]


> [39] oxffff ©   (09.03.07 17:04)
> Есть еще вариант
>
> TXmlNodeAdapter=class
> public
> construcor create(Node:TXmlNode);
> end;


и что с этим делать дальше?


 
oxffff ©   (2007-03-09 17:12) [46]

TXmlNodeAdapter=class
> public
> construcor create(Node:TXmlNode);
> end;

Тот же самый Адаптер, который транслирует удобные вызовы в неудобные.


 
jack128 ©   (2007-03-09 17:12) [47]

Суслик ©   (09.03.07 17:08) [44]
Только как исключительный случай.

приведенный вариант со стримами - это исключительный случай?


 
Джо ©   (2007-03-09 17:16) [48]

Касаемо моего примера со стримом, меня остановило след. соображение.
Безусловно, написание кода это облегчает. Но вот облегчает ли это его чтение посторонним человеком? Подумал, что, скорее всего, только затруднит. Ибо ход мысли такой: «Какой-такой метод у TStream (а в параметрах метода именно и передается тип TStream)? Нету такого. Гм». А хелперы — относительно новая синт. конструкция, далеко не все ее знают. И выходит путаницы.
В таком роде :)


 
oxffff ©   (2007-03-09 17:17) [49]


> oxffff ©   (09.03.07 17:12) [46]
> TXmlNodeAdapter=class
> > public
> > construcor create(Node:TXmlNode);
> > end;
>
> Тот же самый Адаптер, который транслирует удобные вызовы
> в неудобные.


Кстати ты может привести TXmlNode к TXmlNodeEx.
А в TXmlNodeEx дописать твои удобные методы.
И helper не будет нужен вовсе.


 
Игорь Шевченко ©   (2007-03-09 17:17) [50]

jack128 ©   (09.03.07 17:07) [42]


> почему?


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

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

Суслик ©   (09.03.07 17:07) [43]


> вообще-то хелперы и наследовать можно


В исходном коде этого не было :)


 
oxffff ©   (2007-03-09 17:19) [51]


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


+118.

Долой helperы


 
jack128 ©   (2007-03-09 17:21) [52]

Джо ©   (09.03.07 17:16) [48]
А хелперы — относительно новая синт. конструкция

То есть через 3 года, когда эта конструкция станет старой, ты перешишь свой код на хелперы? Бред.

А Ctrl+Click - приведет тебя к реализации хелпера, откуда и можно все узнать.


 
Джо ©   (2007-03-09 17:23) [53]

> [52] jack128 ©   (09.03.07 17:21)
> Джо ©   (09.03.07 17:16) [48]
> А хелперы — относительно новая синт. конструкция
> То есть через 3 года, когда эта конструкция станет старой,
> ты перешишь свой код на хелперы? Бред.

Да не стану я его переписывать. Он и так работает, зачем я буду его трогать?
А новый, возможно, напишу и с хелперами. Не знаю. Я же сказал, что окончательно не определился. Может, эта ветка подкинет мне новую пищу для размышлений. :)


 
Суслик ©   (2007-03-09 17:23) [54]

вообще-то code insight показывает методы хелперов


 
jack128 ©   (2007-03-09 17:25) [55]

Игорь Шевченко ©   (09.03.07 17:17) [50]
Потому что любую хорошую идею умудряются извратить до такого состояния, когда вместо того, чтобы упрощать код, она выполняет прямо противоположную функцию.


oxffff ©   (09.03.07 17:19) [51]
+118.

Долой helperы


Действительно.  Например идею ООП.  

ДОЛОЙ ООП!!!!!!!!!!! ООП - маст дай!!!!!!!!!!!!

А вообще - если человек не в состоянии грамотно использовать такую весьма простую концепцию, как хелперы, уж о том, что он сможет нормально использовать/реализовывать классы и объекты - можно забыть.


 
Игорь Шевченко ©   (2007-03-09 17:25) [56]

Кстати, обычно качественным источником примеров являются файлы, поставляемые вместе c Delphi. В 2006 единственным местом, где используется эта синтаксическая конструкция, является Indy при компиляции под .Net.

Более того, под .Net эти helper"ы вполне оправданы, так как модифицировать CLI вряд ли кто-то в здравом уме решится.

jack128 ©   (09.03.07 17:21) [52]


> А Ctrl+Click - приведет тебя к реализации хелпера, откуда
> и можно все узнать.


А за такие советы, Женя, давить надо, потому что исходный код читается не только в среде.
Племя, блин, младое, незнакомое.


 
GrayFace ©   (2007-03-09 17:27) [57]

Игорь Шевченко ©   (09.03.07 17:04) [38]
"You can define and associate multiple class helpers with a single class type. However, only zero or one class helper applies in any specific location in source code. The class helper defined in the nearest scope will apply"

Эх, такую хорошую вещь кастрировали.


 
Игорь Шевченко ©   (2007-03-09 17:31) [58]

jack128 ©   (09.03.07 17:25) [55]


> А вообще - если человек не в состоянии грамотно использовать
> такую весьма простую концепцию, как хелперы, уж о том, что
> он сможет нормально использовать/реализовывать классы и
> объекты - можно забыть.


Точно. И шаблоны с множественным наследованием и макросами. Таких надо просто отстреливать, чтобы не мешали.


 
jack128 ©   (2007-03-09 17:32) [59]

Игорь Шевченко ©   (09.03.07 17:25) [56]
А за такие советы, Женя, давить надо, потому что исходный код читается не только в среде.
Племя, блин, младое, незнакомое.


Читать хелперы вне IDE - не намного сложнее, чем иерархию классов. Что в первом, что во втором случае - ты должен перерыть все модули, подключеные через uses


 
Джо ©   (2007-03-09 17:32) [60]

Эх, застрелите меня уже в конце концов. Что-то народ и вправду после праздника какой-то агрессивный :(


 
Суслик ©   (2007-03-09 17:33) [61]


>  [60] Джо ©   (09.03.07 17:32)
> Эх, застрелите меня уже в конце концов. Что-то народ и вправду
> после праздника какой-то агрессивный :(

ты это к чему?
что случилось?


 
oxffff ©   (2007-03-09 17:33) [62]


> Долой helperы
>
> Действительно.  Например идею ООП.  
>
> ДОЛОЙ ООП!!!!!!!!!!! ООП - маст дай!!!!!!!!!!!!
>
> А вообще - если человек не в состоянии грамотно использовать
> такую весьма простую концепцию, как хелперы, уж о том, что
> он сможет нормально использовать/реализовывать классы и
> объекты - можно забыть.


Стоп.
Посмотри oxffff ©   (09.03.07 17:17) [49]

Единственная проблема в [49], что здесь привидение типов Not type safe.
Вот здесь и заключается приимущество helperа.

Но стоит вводить helper из-за этого.


 
GrayFace ©   (2007-03-09 17:35) [63]

Игорь Шевченко ©   (09.03.07 17:25) [56]
А за такие советы, Женя, давить надо, потому что исходный код читается не только в среде.

Эта такая редкая ситуация, что на нее нет смысла обращать внимание.


 
Игорь Шевченко ©   (2007-03-09 17:36) [64]

jack128 ©   (09.03.07 17:32) [59]


> Читать хелперы вне IDE - не намного сложнее, чем иерархию
> классов. Что в первом, что во втором случае - ты должен
> перерыть все модули, подключеные через uses


Тебе самому не смешно ? Мне уже.

Читать и думать над прочитанным.

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


 
Игорь Шевченко ©   (2007-03-09 17:36) [65]

GrayFace ©   (09.03.07 17:35) [63]


> Эта такая редкая ситуация, что на нее нет смысла обращать
> внимание.


Ошибаешься


 
oxffff ©   (2007-03-09 17:41) [66]


> Игорь Шевченко ©   (09.03.07 17:31) [58]
> jack128 ©   (09.03.07 17:25) [55]
>
>
> > А вообще - если человек не в состоянии грамотно использовать
>
> > такую весьма простую концепцию, как хелперы, уж о том,
>  что
> > он сможет нормально использовать/реализовывать классы
> и
> > объекты - можно забыть.
>
>
> Точно. И шаблоны с множественным наследованием и макросами.
>  Таких надо просто отстреливать, чтобы не мешали.


Зачем. Человеку нужно время.

to jack128

Почитай внимательно

A class helper type may not declare instance data, but class fields are allowed.

Т.Е. на уровня instanceSize никаких изменений, только методы.
+ Возможно Helper VTB, но которая передается как параметр. (кстати еще не реализовано).

Ну и есть ли смысл. В том чтобы вводить helper, вместо того чтобы написать

так либо adapter oxffff ©   (09.03.07 17:12) [46]

либо non type safe

ClassA=class

end;
classB=Class(ClassA)

end;

var b:ClassB;
   
b:=ClassB(ClassA.create);

Делов то.


 
jack128 ©   (2007-03-09 18:03) [67]

oxffff ©   (09.03.07 17:33) [62]
Вот здесь и заключается приимущество helperа.
Но стоит вводить helper из-за этого.

oxffff ©   (09.03.07 17:41) [66]
Делов то.

угу. Вы не находите, что предлагаете ПОЛНЫЙ аналог хелперов, но этот аналог обильно присыпан граблями?

Игорь Шевченко ©   (09.03.07 17:36) [64]
Читать и думать над прочитанным.

И? Два уровня иерархии - это много?  А без IDE и в двух уровнях рахобраться не просто.


 
Игорь Шевченко ©   (2007-03-09 18:08) [68]

jack128 ©   (09.03.07 18:03) [67]


>  А без IDE и в двух уровнях рахобраться не просто.


Бедные программисты. Без IDE уже никуда. Вот смотри, Женя, есть двольно крупные проекты (операционная система - очень крупный проект_ написанные совершенно без ООП и в то же время абсолютно понятны и относительно легко модифицируемые (для крупных проектов понятие легкости модификации вообще под сомнением) - это Windows и Linux. Могу еще для примера привести СУБД Oracle - тоже на чистом С, без какого либо ООП - и ничего, живут себе, развиваются, дай Аллах каждому проекту столько времени жизни без переписывания набело.

Значит, не такая серебряная пуля это ООП, модульность гораздо важнее, не правда ли ?


 
oldman ©   (2007-03-09 18:09) [69]


> Игорь Шевченко ©  


Поговорку про тщетность метания бисера знаешь?


 
oxffff ©   (2007-03-09 18:12) [70]


> угу. Вы не находите, что предлагаете ПОЛНЫЙ аналог хелперов,
>  но этот аналог обильно присыпан граблями?


Продемострируйте грабли


 
Суслик ©   (2007-03-09 18:12) [71]


> [69] oldman ©   (09.03.07 18:09)
> Поговорку про тщетность метания бисера знаешь?


Ну это же уже хамство какое-то :)


 
oldman ©   (2007-03-09 18:16) [72]


> Суслик ©   (09.03.07 18:12) [71]
> Ну это же уже хамство какое-то :)


Нет. Просто... "Когда слепой ведет слепого..." :)))

(ничего не хочу сказать плохого про ИШ, но ты их переписку почитай)


 
oxffff ©   (2007-03-09 18:18) [73]


> oxffff ©   (09.03.07 17:33) [62]
> Вот здесь и заключается приимущество helperа.
> Но стоит вводить helper из-за этого.
> oxffff ©   (09.03.07 17:41) [66]
> Делов то.
> угу. Вы не находите, что предлагаете ПОЛНЫЙ аналог хелперов,
>  но этот аналог обильно присыпан граблями?


Посмотрите oxffff ©   (09.03.07 17:12) [46].

Опишете грабли.

либо non type safe

ClassA=class

end;
classB=Class(ClassA)

end;

var b:ClassB;
 
b:=ClassB(ClassA.create);

Non Type safe
решается просто

Вводом всего лишь ключа {$HelperСlass}.
Который позволяет приводить типы.

И всего.

Никаких синтаксических конструкций.


 
oxffff ©   (2007-03-09 18:20) [74]

to jack128.
oxffff ©   (09.03.07 18:18) [73]

Привидите пример граблей адаптера.

Привидите пример с non type safe.


 
oxffff ©   (2007-03-09 18:23) [75]

to jack128.

Можете даже назвать ключ {$RestrictFieldsDeclaration}


 
oxffff ©   (2007-03-09 18:27) [76]

Есть еще вариант решения non type safe

class operator Implicit(Obj:ClassA):ClassB;


 
jack128 ©   (2007-03-09 18:28) [77]

Игорь Шевченко ©   (09.03.07 18:08) [68]
модульность гораздо важнее, не правда ли ?

Без сомнения.

Хе. Игорь, а теперь вспомним зачем водятся хелперы. Они вводят для того, чтобы ввести доп. функционал в те классы,  изменить которые мы не можем. System.Object в .NET (для борланда - он недоступен). Тоже самое с TStream.  Прикладной программист не может добавить новый код в Classes.pas

oldman ©   (09.03.07 18:09) [69]
Хамить-то зачем? © oldman


 
jack128 ©   (2007-03-09 18:33) [78]

oxffff ©   (09.03.07 18:27) [76]
class operator Implicit(Obj:ClassA):ClassB;

для классов - нельзя переопределить операторы.  Под Win32.

oxffff ©   (09.03.07 18:18) [73]
Вводом всего лишь ключа {$HelperСlass}.

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

oxffff ©   (09.03.07 18:20) [74]
Привидите пример с non type safe.

var
 O: TSomeObject;
 Helper: TSomeObjectHelper;
begin
 ...
 Helper := TSomeObjectHelper(O);
 ...
 SomeProc(Helper);
end;

procedure


 
euru ©   (2007-03-09 18:33) [79]

Про хелперы.
Года 2-3 назад я выкладывал в кладовку (которая здесь была изначально) исходники, в которых было реализовано некое подобие хелперов для Delphi 7. Суть его была в следующем. Был создан базовый класс. К нему и его потомкам можно было во время исполнения добавлять методы от других потомков этого же базового класса. Таким образом, у объекта во время исполнения появлялись методы, которые не были предусмотрены при компиляции.

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

Возможная область применения хелперов: упрощение структуры и иерархии классов. Например, хелперы могли бы (возможно) решить дилемму глубина иерархии классов - сложность базовых классов. Т.е. часто приходится решать, какой вариант лучше: поместить как можно больше функциональности в базовый класс, тем самым минимизируя количество возможных потомков, либо в базовом классе реализовать минимально необходимую функциональность, а её расширение осуществлять путём наследования.

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

Примеры (названия классов и полей пишу по памяти, так что могу и ошибиться).
1. Поле PasswordChar в классе TEdit. Очень редко используемое поле. С хелперами можно было бы добавлять только к тем объектам TEdit, которым оно действительно нужно.

2. Свойство Dockable у класса TControl. Тоже не для всех контролов и не во всех проектах используется. Можно вынести в отдельный хелпер и подключать по мере необходимости.

3. Дублирование обычных контролов и DB-контролов. С хелперами можно было бы создать обычные контролы, а возможность работы с БД получалась бы подключением DB-хелпера.


 
Игорь Шевченко ©   (2007-03-09 18:34) [80]

jack128 ©   (09.03.07 18:28) [77]

Я помню, зачем вводятся helper"ы. Я также знаю, что для win32 существует масса более очевидных способов расширить функциональность классов. Ключевое слово - очевидность, код в первую очередь должен быть понятным, а видя в коде Memo.Lines.DoWork я в первую очередь теряюсь, во вторую прикладываю усилия для увольнения пишущего подобные вещи, потому что очевидность кода это гораздо более важная составляющая, чем факт использования новомодных фич.


 
oxffff ©   (2007-03-09 18:34) [81]

Class helpers provide a way to extend a class,
but they should not be viewed as a design tool to be used when developing new code. They should be used solely for their intended purpose, which is language and platform RTL binding.


 
jack128 ©   (2007-03-09 18:36) [82]

Сории, случайно надал отправить.

oxffff ©   (09.03.07 18:20) [74]
Привидите пример с non type safe.


procedure SomeProc(O: Tobject); forward;

...

var
O: TSomeObject;
Helper: TSomeObjectHelper;
begin
...
Helper := TSomeObjectHelper(O);
...
SomeProc(Helper);
end;

procedure SomeProc(O: Tobject);
begin
 if O is TSomeObjectHelper then
...
 else ...
 
end;


 
jack128 ©   (2007-03-09 18:38) [83]

oxffff ©   (09.03.07 18:34) [81]
but they should not be viewed as a design tool to be used when developing new code. They should be used solely for their intended purpose, which is language and platform RTL binding.

И как это протеворечит тому, что пишу?


 
oxffff ©   (2007-03-09 18:39) [84]


> jack128 ©   (09.03.07 18:33) [78]
> oxffff ©   (09.03.07 18:27) [76]
> class operator Implicit(Obj:ClassA):ClassB;
> для классов - нельзя переопределить операторы.  Под Win32.

function RefUniversalConverter(a:pointer):pointer
begin
result:=a;
end;

Либо аdapter.

>
> oxffff ©   (09.03.07 18:18) [73]
> Вводом всего лишь ключа {$HelperСlass}.
> чем ввод дополнительного ключа для компилятора, который
> фиг знает работает, отличается от ввода новой синтаксической
> конструкции?
>
> oxffff ©   (09.03.07 18:20) [74]
> Привидите пример с non type safe.
> var
>  O: TSomeObject;
>  Helper: TSomeObjectHelper;
> begin
>  ...
>  Helper := TSomeObjectHelper(O);
>  ...
>  SomeProc(Helper);
> end;
>
> procedure


Подробнее пожалуйста.


 
oxffff ©   (2007-03-09 18:44) [85]


> jack128 ©   (09.03.07 18:36) [82]
> Сории, случайно надал отправить.
>
> oxffff ©   (09.03.07 18:20) [74]
> Привидите пример с non type safe.
>
> procedure SomeProc(O: Tobject); forward;
>
> ...
>
> var
> O: TSomeObject;
> Helper: TSomeObjectHelper;
> begin
> ...
> Helper := TSomeObjectHelper(O);
> ...
> SomeProc(Helper);
> end;
>
> procedure SomeProc(O: Tobject);
> begin
>  if O is TSomeObjectHelper then
> ...
>  else ...
>  
> end;


Мне не понятно, что тебе не нравиться.


 
jack128 ©   (2007-03-09 18:52) [86]

oxffff ©   (09.03.07 18:44) [85]

Мне не понятно, что тебе не нравиться.

мне не нравится, что код
var
 A: TSomeObjectHelper;
begin
...
 Result := TObject(A) is TSomeObjectHelper;
end;
может вернуть False/


 
jack128 ©   (2007-03-09 18:55) [87]

Игорь Шевченко ©   (09.03.07 18:34) [80]
Ключевое слово - очевидность, код в первую очередь должен быть понятным, а видя в коде Memo.Lines.DoWork я в первую очередь теряюсь,


Ну не знаю.  Я не  теряюсь. Для меня достаточно понятно.  Для других программистов из наших - тоже.  Мне этого факта - достаточно.


 
oxffff ©   (2007-03-09 19:11) [88]


> jack128 ©   (09.03.07 18:52) [86]
> oxffff ©   (09.03.07 18:44) [85]
>
> Мне не понятно, что тебе не нравиться.
> мне не нравится, что код
> var
>  A: TSomeObjectHelper;
> begin
> ...
>  Result := TObject(A) is TSomeObjectHelper;
> end;
> может вернуть False/


А какое это отношение имеет к моим примерам.
И зачем передавать A в функцию.


 
oxffff ©   (2007-03-09 19:16) [89]

Интерес вызывает другое

ClassA=class helper for tObject
procedure abc;
end;

Я могу объявить переменную
var
    a:Tobject;
    b:ClassA;
Только с ней сделать ничего не могу.

b. //e2018

b:=a //e2015
a:=b; //e2010

Что за чудеса?


 
Суслик ©   (2007-03-09 19:23) [90]


>  [89] oxffff ©   (09.03.07 19:16)

ты бы составлял примеры кода более понятно.
а то догадываться приходится о чем ты вообще говоришь.


 
jack128 ©   (2007-03-09 19:29) [91]

oxffff ©   (09.03.07 19:16) [89]
Я могу объявить переменную

ИМХО - это баг.  Хелперы как самостоятельные сущности - не имеют смысла.


 
jack128 ©   (2007-03-09 19:31) [92]

oxffff ©   (09.03.07 19:11) [88]
А какое это отношение имеет к моим примерам.
И зачем передавать A в функцию.


То есть зачем?  Знаешь, я таки иногда пишу функции и методы.. И иногда даже передаю в них параметры..


 
oxffff ©   (2007-03-09 19:44) [93]


> jack128 ©   (09.03.07 19:31) [92]
> oxffff ©   (09.03.07 19:11) [88]
> А какое это отношение имеет к моим примерам.
> И зачем передавать A в функцию.
>
> То есть зачем?  Знаешь, я таки иногда пишу функции и методы.
> . И иногда даже передаю в них параметры..


По твоему примеру не понятно, что тебя не устраивает.

Если у тебя

a:Tcontrol;
b:TwinControl;

a:=Tcontrol.create(nil);
b:=TwinControl(A);

procedure Check(a:Tobject);
begin
if a is Twincontrol then
  else
end;

Будет всегда false. Что тебе не нравиться.

Тебе не надо инстанцировать Helper class. Ты просто приводишь к нему.
И все.

Если ты имел что то другое напиши. О чем ты.

Буду через час.


 
Eraser ©   (2007-03-09 20:10) [94]

кстати, отвлекаясь от темы хелперов )

исправили ли наконец баг с горизонтальным "авто скролом" в редакторе кода, когда печатаешь русскими буквами (коментарии, константы)?


 
GrayFace ©   (2007-03-09 20:48) [95]

euru ©   (09.03.07 18:33) [79]
С хелперами можно было бы реализовать второй вариант, а дополнительные возможности подключать к базовому классу или его потомкам по мере необходимости.

Это, как раз, неправильный способ их использования.

euru ©   (09.03.07 18:33) [79]
1. Поле PasswordChar в классе TEdit. Очень редко используемое поле. С хелперами можно было бы добавлять только к тем объектам TEdit, которым оно действительно нужно.

Оно же в оболочке используется, значит обязано присутствовать в TEdit!

Игорь Шевченко ©   (09.03.07 18:34) [80]
Ключевое слово - очевидность, код в первую очередь должен быть понятным, а видя в коде Memo.Lines.DoWork я в первую очередь теряюсь, во вторую прикладываю усилия для увольнения пишущего подобные вещи, потому что очевидность кода это гораздо более важная составляющая, чем факт использования новомодных фич.

С непривычки?

jack128 ©   (09.03.07 18:52) [86]
var
A: TSomeObjectHelper;
begin
...
Result := TObject(A) is TSomeObjectHelper;
end;
может вернуть False/

Ну и что?


 
Игорь Шевченко ©   (2007-03-09 21:06) [96]

euru ©   (09.03.07 18:33) [79]


> 3. Дублирование обычных контролов и DB-контролов. С хелперами
> можно было бы создать обычные контролы, а возможность работы
> с БД получалась бы подключением DB-хелпера.


Это вряд ли. Механизм хелперов предусматривает только дополнительные методы с уже имеющимися свойствами (или с классовыми свойствами, что в данном случае тоже несильно применимо).

Кстати, в случае DB-Aware controls неплохо бы на мой взгляд подошло  множественное наследование и наследуясь от простого контрола и TdataLink можно было бы получать нужный результат. При этом сохранялась бы возмножность независимой модификации обоих базовых классов.


 
Игорь Шевченко ©   (2007-03-09 21:08) [97]

GrayFace ©   (09.03.07 20:48) [95]


> С непривычки?


Дорогой друг, привычка - это сэкономленное время.
Впрочем, кто в молодости не был радикалом...


 
jack128 ©   (2007-03-09 21:16) [98]

GrayFace ©   (09.03.07 20:48) [95]
Ну и что?

То что декларируемое - не соответствует действительному. Это еще допустимо во внутренней реализации классов (думаю многие хранили Integer в TList"е), но тут подобное несоответствие будет везде, где будут используются эти псевдохелперы. Нафиг-нафиг-нафиг.

Игорь Шевченко ©   (09.03.07 21:06) [96]
неплохо бы на мой взгляд подошло  множественное наследование и

БИНГО! :-D


 
oxffff ©   (2007-03-09 23:10) [99]

to jack128
Ответьте на  oxffff ©   (09.03.07 19:44) [93]


 
oxffff ©   (2007-03-09 23:34) [100]


> То что декларируемое - не соответствует действительному.
>  Это еще допустимо во внутренней реализации классов (думаю
> многие хранили Integer в TList"е), но тут подобное несоответствие
> будет везде, где будут используются эти псевдохелперы. Нафиг-
> нафиг-нафиг.


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


 
jack128 ©   (2007-03-09 23:50) [101]

oxffff ©   (09.03.07 19:44) [93]
a:=Tcontrol.create(nil);
b:=TwinControl(A);


Ну.. Видя такой код
я в первую очередь теряюсь, во вторую прикладываю усилия для увольнения пишущего подобные вещи, © Игорь Шевченко   ;-)

Еще раз: Ты предлагаешь те же хелперы, но обильно присыпанные граблями.


 
euru ©   (2007-03-10 00:06) [102]


> GrayFace ©   (09.03.07 20:48) [95]
> Это, как раз, неправильный способ их использования.
Неправильный концептуально или с точки зрения реализации хелперов в Delphi?


> Оно же в оболочке используется, значит обязано присутствовать
> в TEdit!
Честно говоря, про оболочку я не понял. В примере я рассматривал гипотетический TEdit, а не из VCL.


> Игорь Шевченко ©   (09.03.07 21:06) [96]
Это, я так понимаю, поведение хелперов, реализованных в Delphi.
Я же рассматривал для чего вообще можно применять хелперы.


 
oxffff ©   (2007-03-10 00:25) [103]


> jack128 ©   (09.03.07 23:50) [101]
> oxffff ©   (09.03.07 19:44) [93]
> a:=Tcontrol.create(nil);
> b:=TwinControl(A);
>
> Ну.. Видя такой код
> я в первую очередь теряюсь, во вторую прикладываю усилия
> для увольнения пишущего подобные вещи, © Игорь Шевченко
>   ;-)
>
> Еще раз: Ты предлагаешь те же хелперы, но обильно присыпанные
> граблями.


Хорошо. Паттерн адаптер тебя не устраивает?


 
oxffff ©   (2007-03-10 00:35) [104]


> > Еще раз: Ты предлагаешь те же хелперы, но обильно присыпанные
>
> > граблями.


Граблей нет. Мне кажется грабли пытаешься ты сам выдумать. И у тебя не получается.

Особенно про это

A: TSomeObjectHelper;
begin
...
Result := TObject(A) is TSomeObjectHelper;
end;
может вернуть False/

Будет всегда возвращать false
Тебе нужно просто использовать with HelperClass(BaseClassObj) и всего.

Если тебе не нравиться жесткое приведение типов используй RefUniversalConverter. Можно даже inline.

Либо адаптер.

Граблей нет.

:(

Соорудили сомнительный велосипед под названием Helper. Зачем?

Пусть будет?


 
jack128 ©   (2007-03-10 00:44) [105]

oxffff ©   (10.03.07 0:25) [103]
Паттерн адаптер тебя не устраивает?


вполне. Но он предусматривает создание НОВОГО объекта.  Собственно у нас так и есть, есть некий
TGsFiler = class
public
 constrcutor Create(AStream: TStream);
 function ReadString: string;
 procedure WriteString(const S: string);
 // И далее по списку.
end;

И во всех классах, которые должны уметь стримится - они стримятся в этот GsFiler.
Но сие не всегда удобно. На каждый чих создовать и тут же уничтожать объект задалбывает довольно быстро.


 
jack128 ©   (2007-03-10 00:49) [106]

oxffff ©   (10.03.07 0:35) [104]
Тебе нужно просто использовать with HelperClass(BaseClassObj) и всего.

вот вот.  То есть я должен всегда использовать ЗАВЕДОМО небезопасную конструкцию.
Сие есть - плохо. И это не обсуждается. Прямое привидение типов для объектов лично я стараюсь не использовать, после того, как пару часов искал опечатку...

oxffff ©   (10.03.07 0:35) [104]
используй RefUniversalConverter

Что это такое?


 
jack128 ©   (2007-03-10 00:56) [107]

Ладно, я выхожу из обсуждения. Чуствую - все останутся при  своих мнениях.


 
GrayFace ©   (2007-03-10 11:59) [108]

euru ©   (10.03.07 0:06) [102]
Неправильный концептуально или с точки зрения реализации хелперов в Delphi?

Я про Дельфийские. Если б не было ограничения [38], то не знаю, насколько такое было бы хорошо. Вообще, как-то нелогично - если реализовывать функциональность в гепотетических хелперах, то им вполне могут понадобиться переменные, а их надо добавлять в самом классе, все получается нараскарячку. А если в гипотетических хелперах иметь возможность объявлять переменные, то это либо ничем не отличается от множественного наследования, либо несет еще больше граблей.


 
oxffff ©   (2007-03-10 12:20) [109]


> Ладно, я выхожу из обсуждения. Чуствую - все останутся при
>  своих мнениях.


Да нет, это диалог. Я могу с вами согласиться.
Что мне лично не нравиться, так это новая синтаксическая конструкция.
И всего. А так я разделяю и вашу точку зрения.

Нужны дополнения в язык. Только их необходимо взвесить, главное без оглядки .NET. Хотя это не реально.
Они же хотят mix-ить managed и Unmanaged код на Delphi в будущем.


 
Игорь Шевченко ©   (2007-03-11 00:03) [110]

euru ©   (10.03.07 00:06) [102]


> Это, я так понимаю, поведение хелперов, реализованных в
> Delphi.
> Я же рассматривал для чего вообще можно применять хелперы.
>


А хелперов вроде нигде больше нету. В C# насколько мне известно вообще никакие примеси не разрешены, в С++ полностью реализовано множественное наследование, что происходит в Java - честно говорю, не знаю. Про остальные языки ничего не говорю, потому что не распространены.


 
euru ©   (2007-03-11 00:51) [111]


> GrayFace ©   (10.03.07 11:59) [108]


> Я про Дельфийские.
Про эти ничего не могу сказать из-за неимения Delphi. Но по обсуждению в этой ветке, я так понял, на них наложено множество ограничений, которые не позволяют в полной мере использовать их возможности. Вообще, как мне показалось из периодически возникающих здесь тем, появляющиеся в Delphi новые возможности чаще всего носят не концептуальный, а конъюнктурных характер. При этом в погоне за модой, конкурентами вводятся дополнительные понятия, но их концептуальность низка. Например, с одной стороны, ввели возможность в записях (record) использовать методы и остановились. А с другой стороны, в Delphi (по крайней мере, до 7-й версии) имеется тип object. Тот же record, только ещё имеется возможность наследования и полиморфизма. По-моему, лучше бы реабилитировали object или перенесли бы на record весь функционал object.


> если реализовывать функциональность в гепотетических хелперах,
>  то им вполне могут понадобиться переменные, а их надо добавлять
> в самом классе, все получается нараскарячку.
Почему в самом классе? В своих экспериментах с как-бы-хелперами я реализовывал возможность использования переменных в самих хелперах. Не вижу в этом ничего нереального. Конечно, класс, к которому присоединяется хелпер, об этих переменных ничего не знает. Но, с одной стороны, ему, возможно, эта информация и не нужна, а с другой стороны, у меня имелась возможность замещать метод класса методом хелпера, который об этих переменных осведомлён хорошо.


> то либо ничем не отличается от множественного наследования,
>  либо несет еще больше граблей.
Отличается хотя бы тем, что не приводит к появлению нового класса. А вопрос граблей мной в экспериментах не рассматривался, потому что преследовались другие цели. :)


 
Eraser ©   (2007-03-11 01:04) [112]

> [111] euru ©   (11.03.07 00:51)


> А с другой стороны, в Delphi (по крайней мере, до 7-й версии)
> имеется тип object. Тот же record

это далеко не тот же record.
да и вообще, как по-мне, так не нужны в структурах методы, на то объекты существуют.


 
euru ©   (2007-03-11 01:09) [113]


> Eraser ©   (11.03.07 01:04) [112]
> это далеко не тот же record.
И в чём же его "нетожесть"?


 
GrayFace ©   (2007-03-11 01:25) [114]

Eraser ©   (11.03.07 1:04) [112]
да и вообще, как по-мне, так не нужны в структурах методы, на то объекты существуют.

Нужны, например, для комплесных чисел.


 
Eraser ©   (2007-03-11 01:29) [115]

> [113] euru ©   (11.03.07 01:09)

на сколько мне известно, обжекты поддерживают наследование.. да и методы у них есть, хоть и статические, т.о. обжект это не просто участок памяти со строго обозначенные поля, размер которого равен сумме этих полей + выравнивание,  к которым есть прямой доступ у юзера, а какие-то поля + метаданные, находящиеся в самом объекте. По-моему методы в записях реализованы через compiler magic.


 
Eraser ©   (2007-03-11 01:31) [116]

> [114] GrayFace ©   (11.03.07 01:25)

В данном случае должны применяться объекты тогда, но это в идеале, когда компьютеры будут мощные и памяти будет много.. ))


 
euru ©   (2007-03-11 02:13) [117]


> Eraser ©   (11.03.07 01:29) [115]
Реализация функциональности в языке программирования, по-моему, не слишком должна беспокоить программиста.

Концептуальное различие между типами class и object в том, что выделение памяти для объектов типа class происходит динамически (при вызове их конструктора), а для объектов типа object - статически, как для обычных переменных. Во всём остальном эти типы, в принципе, схожи.

Теперь сравним типы record и object. Оба типа являются структурами, содержащими поля других типов. Как для record, так и для object память выделяется статически во время компиляции. Это их сходства. Различия заключаются в том, что record предназначен только для хранения данных, а object кроме этого содержит в себе также методы обработки этих данных, а также позволяет управлять областью их видимости и возможностями наследования и полиморфизма.

Теперь разработчики добавляют для типов record возможность определения в них методов обработки (конъюнктурное решение, вызванное, я так понимаю, поддержкой в Delphi технологии .Net). Но раз уже использовалась такая возможность в типах object, почему бы не перенести всю функциональность object на record (раз уж они с таким упорством открещиваются от object), сделав record более гибким, чем в C#. А object могли бы обозвать синонимом record в целях обратной совместимости.


 
GrayFace ©   (2007-03-11 13:50) [118]

Eraser ©   (11.03.07 1:31) [116]
В данном случае должны применяться объекты тогда, но это в идеале, когда компьютеры будут мощные и памяти будет много.. ))

В Delphi и применяются Custom Variants для этого, но это очень громоздко.

Eraser ©   (11.03.07 1:29) [115]
на сколько мне известно, обжекты поддерживают наследование.. да и методы у них есть, хоть и статические

Даже виртуальные возможны, и конструкторы с деструкторами %)

Eraser ©   (11.03.07 1:29) [115]
По-моему методы в записях реализованы через compiler magic.

Ну думаю, что это чем-то отличается от методов в объектах и классах. Только что такое compiler magic?


 
oxffff ©   (2007-03-11 14:06) [119]


> Eraser ©   (11.03.07 1:29) [115]
> на сколько мне известно, обжекты поддерживают наследование.
> . да и методы у них есть, хоть и статические
> Даже виртуальные возможны, и конструкторы с деструкторами
> %)


Еще и динамические.


 
pasha_golub ©   (2007-03-11 15:02) [120]


> jack128 ©   (09.03.07 21:16) [98]



> думаю многие хранили Integer в TList"е

Откуда ты узнал? :))


 
Eraser ©   (2007-03-11 15:19) [121]

> [117] euru ©   (11.03.07 02:13)

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


 
oxffff ©   (2007-03-11 16:02) [122]


> Теперь разработчики добавляют для типов record возможность
> определения в них методов обработки (конъюнктурное решение,
>  вызванное, я так понимаю, поддержкой в Delphi технологии
> .Net). Но раз уже использовалась такая возможность в типах
> object, почему бы не перенести всю функциональность object
> на record (раз уж они с таким упорством открещиваются от
> object), сделав record более гибким, чем в C#. А object
> могли бы обозвать синонимом record в целях обратной совместимости.
>


Object мог запутать.
Поскольку к нему можно было применить Typeof для получения VTB.
А виртульные методы в record не объявишь.


 
oxffff ©   (2007-03-11 16:07) [123]


> Eraser ©   (11.03.07 15:19) [121]
> > [117] euru ©   (11.03.07 02:13)
>
> это всё конечно хорошо, но главное приемущество записи в
> том, что её можно просто взять и скопировать или сохранить
> куда-то, без помощи каких-то специальных методов самой записи.
>  Не знаю правда можно ли так поступать с object"ами, но
> думаю что нет, вряд ли объекты можно плодить простым копированием.
>  А насчет того, где выделяется память - это уже второй вопрос,
>  частенько и под записи (и осоенно массивы заисей) память
> приходится выделять через GetMem.


В system.pas

Compiler magic

procedure       _ObjCopy;

Правда по коду явно не глубокое копирование, как прочем и у record.


 
euru ©   (2007-03-11 16:36) [124]


> Eraser ©   (11.03.07 15:19) [121]
> главное приемущество записи в том, что её можно просто взять
> и скопировать или сохранить куда-то, без помощи каких-то
> специальных методов самой записи. Не знаю правда можно ли
> так поступать с object"ами, но думаю что нет, вряд ли объекты
> можно плодить простым копированием.
Как раз object (в отличие от class) можно копировать так же, как и record.


 
jack128 ©   (2007-03-11 20:43) [125]

Опс. Пропустил ответ:
Игорь Шевченко ©   (09.03.07 17:04) [38]
Какие предки и потомки у helper"ов ? Каждый helper является равноправным.


Из хелпа Turbo Delphi
The syntax for declaring a class helper is:
type
  identifierName = class helper [(ancestor list)] for classTypeIdentifierName
    memberList
  end;
The ancestor list is optional.
A class helper type may not declare instance data, but class fields are allowed.


 
Игорь Шевченко ©   (2007-03-11 20:49) [126]

jack128 ©   (11.03.07 20:43) [125]

Во-первых, в твоем коде были равноправные хелперы.
Во-вторых, а не затруднит ли тебя объяснить физический смысл ancestor list в данном определении ?


 
vuk ©   (2007-03-11 20:56) [127]

Кстати. Почему они там написали именно "ancestor list" понять трудно. Наверное все-таки, как и у класса, должно быть "ancestorClass" А вот зачем хелперу предок - это понятно. Например, если есть желание расширить существующий хелпер...


 
Игорь Шевченко ©   (2007-03-11 21:00) [128]

vuk ©   (11.03.07 20:56) [127]


> Например, если есть желание расширить существующий хелпер.
> ..


Например каким образом ?


 
jack128 ©   (2007-03-11 21:03) [129]

Игорь Шевченко ©   (11.03.07 20:49) [126]
Во-первых, в твоем коде были равноправные хелперы.

Я потом исправился :-)
vuk ©   (11.03.07 20:56) [127]
Почему они там написали именно "ancestor list" понять трудно.

Ну например
vuk ©   (11.03.07 20:56) [127]
если есть желание расширить существующий хелперЫ...

;-)


 
vuk ©   (2007-03-11 21:04) [130]

to Игорь Шевченко ©   (11.03.07 21:00) [128]:
>Например каким образом ?
Издеваисся? :) Унаследовать хелпер от существующего и добавить нужную функциональность.


 
Игорь Шевченко ©   (2007-03-11 21:07) [131]

vuk ©   (11.03.07 21:04) [130]

Не вижу причины нафига это нужно.
Вот ей-богу, не вижу. Если хелпер содержит только набор методов и классовых свойств, нафига может потребоваться его расширять ?

Объясни бестолковому.


 
vuk ©   (2007-03-11 21:09) [132]

to jack128 ©   (11.03.07 21:03) [129]:
>Ну например
>vuk ©   (11.03.07 20:56) [127]
>если есть желание расширить существующий хелперЫ...
Дак у класса-то только один предок бывает... Хелпер-то, он тоже класс, хоть и специальный.


 
vuk ©   (2007-03-11 21:15) [133]

to Игорь Шевченко ©   (11.03.07 21:07) [131]:
>Если хелпер содержит только набор методов и классовых свойств, нафига
>может потребоваться его расширять ?
Ровно так же как с классами. Ну вот не хватило тебе функциональности в существующем хелпере. Не переписывать же хелпер с нуля только для того, чтобы добавить один-два метода?


 
jack128 ©   (2007-03-11 21:21) [134]

vuk ©   (11.03.07 21:09) [132]
Хелпер-то, он тоже класс, хоть и специальный.

Нет.  Он - не класс. Ну ни коем образом не класс. Хелпер - это просто сборник методов и ничего более.  Если те нужно объеденить 2 сборника в один - просто объявляешь наследника обоих..


 
Игорь Шевченко ©   (2007-03-11 21:24) [135]

vuk ©   (11.03.07 21:15) [133]

Э...а я разве существующим не смогу воспользоваться ? Зачем переписывать с нуля ?

Или это так же как с наследованием интерфейсов ?


 
jack128 ©   (2007-03-11 21:31) [136]

Игорь Шевченко ©   (11.03.07 21:24) [135]
Э...а я разве существующим не смогу воспользоваться ? Зачем переписывать с нуля ?


Например у тя есть helper для TStrings.  Он используется нескольких приложениях, в том числе и в консольных.
Терь те нужно сделать добавить в него метод, но этот метод требует модуля Forms.  ТО есть если ты добавить этот метод в уже существующий хелпер, то все твои консольные приложения потянут за собой Forms. Не очень хорошая ситуация, согласись ;-)

Кста, множественное наследование хелперов - не фига не работает :-)


 
oxffff ©   (2007-03-11 21:36) [137]


> Кста, множественное наследование хелперов - не фига не работает
> :-)


Приведи код


 
jack128 ©   (2007-03-11 21:37) [138]

type
 TObjectHelper1 = class helper for TObject
 public
   procedure Test;
 end;

 TObjectHelper2 = class helper for TObject
 public
   procedure Test2;
 end;

 TObjectHelper3 = class helper (TObjectHelper1, TObjectHelper2) for TObject
 public
   procedure Test3;
 end;

procedure TForm9.FormCreate(Sender: TObject);
begin

end;

{ TObjectHelper1 }

procedure TObjectHelper1.Test;
begin
 ShowMessage("TObjectHelper1.Test");
end;

{ TObjectHelper2 }

procedure TObjectHelper2.Test2;
begin
 ShowMessage("TObjectHelper2.Test");
end;

{ TObjectHelper3 }

procedure TObjectHelper3.Test3;
begin
 ShowMessage("TObjectHelper3.Test");
end;

end.


 
jack128 ©   (2007-03-11 21:38) [139]

jack128 ©   (11.03.07 21:37) [138]
TObjectHelper3 = class helper (TObjectHelper1, TObjectHelper2) for TObject

[Pascal Error] Unit9.pas(36): E2029 ")" expected but "," found


 
vuk ©   (2007-03-11 21:40) [140]

jack128 ©   (11.03.07 21:21) [134]:
>Хелпер - это просто сборник методов и ничего более.
Ага, а класс - не сборник. Или вот, например, интерфейс. Это что такое?

>Если те нужно объеденить 2 сборника в один - просто объявляешь
>наследника обоих..
Сам-то пробовал перед тем, как написать? ;)

to Игорь Шевченко ©   (11.03.07 21:24) [135]:
>Э...а я разве существующим не смогу воспользоваться ?
Ну да, в один конкретный момент доступен только один хелпер - ближайший по видимости. То есть если хотим свой использовать, то другие будут невидимы. Совместить функциональность можно только наследованием.


 
jack128 ©   (2007-03-11 21:44) [141]

vuk ©   (11.03.07 21:40) [140]
Или вот, например, интерфейс. Это что такое?

Интерфейсы - это именно сборники методов.   Они, кстати, множественное наследование поддерживают ;-)


 
Игорь Шевченко ©   (2007-03-11 21:46) [142]

jack128 ©   (11.03.07 21:31) [136]


> Например у тя есть helper для TStrings.  Он используется
> нескольких приложениях, в том числе и в консольных.
> Терь те нужно сделать добавить в него метод, но этот метод
> требует модуля Forms.  ТО есть если ты добавить этот метод
> в уже существующий хелпер, то все твои консольные приложения
> потянут за собой Forms.


Я могу написать несколько helper"ов для одного класса (для того же Tstrings)

Костыль на костыле получается. Suxx


 
Игорь Шевченко ©   (2007-03-11 21:48) [143]

vuk ©   (11.03.07 21:40) [140]


> в один конкретный момент доступен только один хелпер - ближайший
> по видимости. То есть если хотим свой использовать, то другие
> будут невидимы


А явно имя квалифицировать не получится ?


 
oxffff ©   (2007-03-11 21:48) [144]


> >Если те нужно объеденить 2 сборника в один - просто объявляешь
>
> >наследника обоих..
> Сам-то пробовал перед тем, как написать? ;)


Никаких препятствий для этого нет.

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

Только судя по всему ancestor list - это опечатка  .


 
oxffff ©   (2007-03-11 21:56) [145]


> А явно имя квалифицировать не получится ?


Не работает.


 
Игорь Шевченко ©   (2007-03-11 22:01) [146]

oxffff ©   (11.03.07 21:56) [145]


> Не работает.


Ну и ладно. Делать надстройку над костылем - ну не понимаю я, нафига это надо, когда есть ясный и понятный механизм наследования.

И кроме того, простые процедуры тоже пока никто не отменял в Delphi для Win32.


 
oxffff ©   (2007-03-11 22:06) [147]


> И кроме того, простые процедуры тоже пока никто не отменял
> в Delphi для Win32.


Верно только когда в модуле множество "help" процедур и функций для различных классов. То class helper позволяет группировать их по функциональности. Поэтому с этой точки зрения удобно увидить их в нужном scope объекта.

Но лично я для себя вижу больше плюсов от record help.


 
oxffff ©   (2007-03-11 22:11) [148]

Естественно ноги растут из .NET struct c методами и интерфейсами. Только понятно, что в самой области памяти занимаемой структурой нет никаких сслылок аля всех тех которые по отрицательному смещению от VTB.
Да и не нужны они, поскольку нет наследования для структур. Поэтому тип известен на этапе компиляции и однозначно можно вызвать метод или получить интерфейс для этого типа.

И все это плюс. Хотя в плане scope


 
Игорь Шевченко ©   (2007-03-11 22:13) [149]

oxffff ©   (11.03.07 22:06) [147]


> Верно только когда в модуле множество "help" процедур и
> функций для различных классов. То class helper позволяет
> группировать их по функциональности. Поэтому с этой точки
> зрения удобно увидить их в нужном scope объекта.


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


 
oxffff ©   (2007-03-11 22:14) [150]


>
> Ну и ладно. Делать надстройку над костылем - ну не понимаю
> я, нафига это надо, когда есть ясный и понятный механизм
> наследования.


Что касаемо этого, то help очень однозначно определяет область их приминения


Class helpers provide a way to extend a class, but they should not be viewed as a design tool to be used when developing new code. They should be used solely for their intended purpose, which is language and platform RTL binding.



 
oxffff ©   (2007-03-11 22:15) [151]


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


Ответ в [150]


 
Игорь Шевченко ©   (2007-03-11 22:19) [152]

oxffff ©   (11.03.07 22:14) [150]

Я читать умею, спасибо. И еще раз могу сказать, что для сопряжения System.Object из .Net Framework и TObject без особой потери совместимости со старым кодом helper"ы вполне уместно использовать, что в Borland и сделали. Но больше причины для их применения я не вижу. Даже в старом коде.


 
oxffff ©   (2007-03-11 22:19) [153]

Книги нужно читать и всегда думать.

Например Гамма, Хелм, Джонсон, Влисидесс
Тот же Буч
 тот же Ларман
используют в качестве примеров C++.

Но  заверяю вас, да и вы сами знаете.
В delphi есть языковые средства которые позволяют решить проблему проще и элегантнее.

Могу сказать, книги пора уже самим писать. :)


 
oxffff ©   (2007-03-11 22:22) [154]


> Даже в старом коде.


В своем безусловно.

А чужом, который нельзя модифицировать?


 
Игорь Шевченко ©   (2007-03-11 22:46) [155]

oxffff ©   (11.03.07 22:19) [153]


> В delphi есть языковые средства которые позволяют решить
> проблему проще и элегантнее.


Безусловно. Но думая об элегантности неплохо бы еще думать о тех, кто будет написанный элегантный код читать. И элегантность - это не напихивание всех новомодных фич ради фич.

oxffff ©   (11.03.07 22:22) [154]


> А чужом, который нельзя модифицировать?


И что ? Никто не запрещает наследоваться от классов в чужом коде, никто не запрещает писать процедуры вокруг классов чужого кода.
Главное, что объявив процедуру со своим именем, ты делаешь очевидным тот факт, что используется твое собственное расширение чужого кода, а написав helper и вызывая его метод у объекта, ты вносишь путаницу, потому что противоречишь интерфейсу чужого класса.


 
vuk ©   (2007-03-11 22:51) [156]

to jack128 ©   (11.03.07 21:44) [141]:
>Они, кстати, множественное наследование поддерживают ;-)
И давно? Нет, про множественную реализацию, это я в курсе. Но это не наследование и оно не у интерфейсов, а у классов.


 
ТЮзер (в нете через паяльник)   (2007-03-11 23:13) [157]

Читаю, читаю, .... Кто-нибудь может привести примитивный пример, что такое эти хелперы, и где они удобны? У меня семерка.


 
oxffff ©   (2007-03-11 23:17) [158]


> И что ? Никто не запрещает наследоваться от классов в чужом
> коде


Хорошо. Предположим. Мне нужно особую функциональность для объекта опеределенного типа стороннего разработчика.

Я определяю класс наследник. И привожу объект к наследнику. О чем я писал выше.

oxffff ©   (09.03.07 18:18) [73]
oxffff ©   (10.03.07 00:35) [104]

Да это решение. Но к сожалению нет способа запретить определение virtual, dynamic(message) методов. Да и привидение будет не безопасным.
Здесь сам разработчик берет на себя эти гарантии.
Другой после этого может и нарушить binary compatibility определив несколько виртуальных или динамических процедур у наследника.
Далее при приведнии будет не понятно.
Почему function ClassType: TClass; возвращает TBaseType вместо дочернего.

В этом решении тоже очень много невыразительности и противоречивости.
Но как костыль тоже подойдет.


> никто не запрещает писать процедуры вокруг классов чужого
> кода.


Классов может быть много и процедур тоже.
А вот иметь общий scope это удобно.


 
Игорь Шевченко ©   (2007-03-11 23:23) [159]

oxffff ©   (11.03.07 23:17) [158]


> Классов может быть много и процедур тоже.
> А вот иметь общий scope это удобно.


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

С чего началась дискуссия - с вызова Memo.Lines.DoWork. Я смотрю в help - у TStrings нету метода DoWork. Впадаю в ступор.


 
ТЮзер (в нете через паяльник)   (2007-03-11 23:26) [160]

А у хелпера есть DoWork? Или что-то еще там есть?


 
oxffff ©   (2007-03-11 23:28) [161]


> Ты никак не хочешь понять один умный вещь - у чужих разработчиков
> интерфейс класса обычно документирован. И использующий код
> в первую очередь будет поиcках понимания методов читать
> документацию, а не гадать, кто же догадался придумать супер-
> пупер хелпер в котором объявлен метод, вызываемый в коде.
>


С этой точки зрения нет ничего проще документировать и helper методы тоже.
Ведь все равно придется описывать процедуры и функции.

Документация ваша и вам также ее придется писать и для своих процедур и функций. Только процедуры и функции будет еще и разбросаны.

Так что описывать придется и то и другое.


 
oxffff ©   (2007-03-11 23:29) [162]


> А у хелпера есть DoWork? Или что-то еще там есть?


Дык, вы почитайте. Мне все равно вам не объяснить.


 
oxffff ©   (2007-03-11 23:31) [163]


>  Я смотрю в help - у TStrings нету метода DoWork. Впадаю
> в ступор.


Дык вы же смотрите свою документацию.
А почему вы не описали в ней процедуры и функции?


 
ТЮзер (в нете через паяльник)   (2007-03-11 23:33) [164]

> oxffff ©   (11.03.07 23:29) [162]

Мне можно объяснить. Просто я не в курсе, что такое хелпер.


 
Игорь Шевченко ©   (2007-03-11 23:34) [165]

oxffff ©   (11.03.07 23:28) [161]


> С этой точки зрения нет ничего проще документировать и helper
> методы тоже.
> Ведь все равно придется описывать процедуры и функции.


То есть, ты предлагаешь выпустить дополнение к help по vcl, в котором будет сказано, что встретив метод DoWork у Memo.Lines надо не пугаться ?
Десяток разработчиков напишет два десятка helperов к TMemoStrings, каждый из них выпустит свою документацию, а программист читающий код будет держать в голове, что надо еще несколько источников просмотреть ?

Suxx


 
oxffff ©   (2007-03-11 23:35) [166]

Согласитесь что проблема надумана.
Конечно я не собираюсь использовать их повсеместно. Поскольку свои проекты я веду сам. То  мне нужен рефакторинг. А если чужые проекты, то я буду знать что есть легальные средства расширения, хотя бы из-за общего scope.


 
oxffff ©   (2007-03-11 23:41) [167]


> То есть, ты предлагаешь выпустить дополнение к help по vcl,
>  в котором будет сказано, что встретив метод DoWork у Memo.
> Lines надо не пугаться ?
> Десяток разработчиков напишет два десятка helperов к TMemoStrings,
>  каждый из них выпустит свою документацию, а программист
> читающий код будет держать в голове, что надо еще несколько
> источников просмотреть ?
>
> Suxx


Хорошо. Если вы определили набор функций и процедур для расширения, которые хотят использовать другие. Вы все равно будете писать документацию.

Человек получает документацию с набором средств и ему все равно придется ее читать будь то helper или набор процедур и функций.

Поэтому проблема надумана.


 
Игорь Шевченко ©   (2007-03-11 23:43) [168]

oxffff ©   (11.03.07 23:35) [166]


> Согласитесь что проблема надумана.


В каждой шутке есть доля правды.


> Поскольку свои проекты я веду сам. То  мне нужен рефакторинг.
>  А если чужые проекты, то я буду знать что есть легальные
> средства расширения, хотя бы из-за общего scope.


Я все-таки предпочитаю, чтобы у знакомых классов не встречались неожиданные методы. Согласись, что за время работы с той же VCL программист запоминает интерфейс тех классов, с которыми ему приходится регулярно иметь дело, а встретив неожиданный метод легко впасть в ступор. Можно безусловно и в среде посмотреть, но это долго и отвлекает от основного занятия - понимания кода.


 
Игорь Шевченко ©   (2007-03-11 23:47) [169]

oxffff ©   (11.03.07 23:41) [167]


> Хорошо. Если вы определили набор функций и процедур для
> расширения, которые хотят использовать другие. Вы все равно
> будете писать документацию.


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

Посмотри же, наконец, где сам Борланд применяет helperы.

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


 
oxffff ©   (2007-03-11 23:47) [170]


> Я все-таки предпочитаю, чтобы у знакомых классов не встречались
> неожиданные методы. Согласись, что за время работы с той
> же VCL программист запоминает интерфейс тех классов, с которыми
> ему приходится регулярно иметь дело, а встретив неожиданный
> метод легко впасть в ступор. Можно безусловно и в среде
> посмотреть, но это долго и отвлекает от основного занятия
> - понимания кода.


Но коли человек согласился использовать чужую библиотеку с исходниками  то проблемы как использовать

-процедуры и функции или
-helper или
-adapter

Эти проблемы его.


 
oxffff ©   (2007-03-11 23:49) [171]


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


Все рано или поздно подтягиваются, кто работает в команде.
Кент Бек и его XP говорит об этом.


 
oxffff ©   (2007-03-11 23:51) [172]


> Посмотри же, наконец, где сам Борланд применяет helperы.


Закончу dial up и обязательно посмотрю сегодня.


 
Игорь Шевченко ©   (2007-03-11 23:59) [173]

oxffff ©   (11.03.07 23:49) [171]


> Все рано или поздно подтягиваются, кто работает в команде.
>
> Кент Бек и его XP говорит об этом.


У меня несколько иные впечатления чем у Бека. Может мне не повезло, а может, наоборот, Беку повезло.

И потом, не так страшен мессия, как его апостолы. Апостолов Бека надо давить в зародыше, потому что они из книги про ХР выбирают только передвижение стульев.


 
oxffff ©   (2007-03-12 00:02) [174]


> И потом, не так страшен мессия, как его апостолы. Апостолов
> Бека надо давить в зародыше, потому что они из книги про
> ХР выбирают только передвижение стульев.


Кстати я не сторонник XP.
Но есть практики, которые мне симпатичны.


 
Игорь Шевченко ©   (2007-03-12 00:18) [175]

oxffff ©   (12.03.07 00:02) [174]

Так тот же Бек или его апостолы в один голос заявляют, что всех преимуществ можно достичь, только применяя всю без исключений методику. А по отдельности да, вполне приличные вещи написаны, начиная от ежедневной сборки.

Но стулья двигать - это нонсенс :)


 
jack128 ©   (2007-03-12 01:02) [176]

vuk ©   (11.03.07 22:51) [156]
И давно? Нет, про множественную реализацию, это я в курсе. Но это не наследование и оно не у интерфейсов, а у классов.

Нет - это мне спать пора :-)


 
euru ©   (2007-03-12 01:07) [177]


> Игорь Шевченко ©   (11.03.07 23:23) [159]


> С чего началась дискуссия - с вызова Memo.Lines.DoWork.
> Я смотрю в help - у TStrings нету метода DoWork. Впадаю
> в ступор.
А с виртуальными методами разве не так? В справке описано одно поведение, в программе наблюдается несколько (или радикально) другое. Неужели это тоже вызовет ступор?


 
Игорь Шевченко ©   (2007-03-12 10:46) [178]

euru ©   (12.03.07 01:07) [177]


> А с виртуальными методами разве не так? В справке описано
> одно поведение, в программе наблюдается несколько (или радикально)
> другое. Неужели это тоже вызовет ступор?


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


 
euru ©   (2007-03-12 11:38) [179]


> Игорь Шевченко ©   (12.03.07 10:46) [178]
Называются-то они как в документации, но вот действия могут выполнять не совсем те, что в документации описаны, потому что разработчик создал потомка и перекрыл в нём эти виртуальные методы.

Более того, если наличие нового метода, непредусмотренного документацией, может быть обнаружена на этапе просмотра листингов, то нестандарное поведение (отличающееся от описания в документации), скорее всего, будет обнаружено только на этапе исполнения программы.


 
oxffff ©   (2007-03-12 11:45) [180]

Because records have a default no-argument constructor, any user-defined record constructor must have one or more parameters.

Интересно

Если объявить в record такой конструктор
constructor My;

то не ругается.

А если такой  

constructor Create;

то ругается
[Pascal Error] Unit1.pas(14): E2394 Parameterless constructors not allowed on record types.


 
Игорь Шевченко ©   (2007-03-12 12:14) [181]

euru ©   (12.03.07 11:38) [179]

Мы о разном. Я говорю об удобстве чтения кода, о том, что встречая документированные методы у документированных классов, программист в уме определяет вероятное поведение программы. Ключевое слово - вероятное. Если кто-то спьяну сделал виртуальный метод, который делает совершенно иное, чем описано, то пусть получает свой эцих с гвоздями и перевоспитывается


 
euru ©   (2007-03-12 12:43) [182]


> Игорь Шевченко ©   (12.03.07 12:14) [181]
Ну так если встретился метод, неописанный в документации, неужели сразу не возникнет мысль (тем более, зная о наличии в языке такой конструкции как helper), что это творение стороннего разработчика, который расширял стандартный класс?

А далее как и с любыми разработками третьих лиц: поиск информации в их документации либо поиск в исходниках.


 
Игорь Шевченко ©   (2007-03-12 12:47) [183]

euru ©   (12.03.07 12:43) [182]

Найти можно все, что угодно и где угодно, было бы время. А его, времени, обычно нету. Можно и методы называть meth1, meth2, meth3, все равно, со временем разберешься, что они делают, не так ли ?


 
oxffff ©   (2007-03-12 12:50) [184]

Пока Дмитрий Тимохов еще пишет свой блог.
Мы уже читаем часть 3

http://hallvards.blogspot.com/


 
Игорь Шевченко ©   (2007-03-12 13:11) [185]

oxffff ©   (12.03.07 12:50) [184]


> http://hallvards.blogspot.com/


"Neat hack, no? ;)"

Вот таких вот вещей и хотелось бы избегать


 
vuk ©   (2007-03-12 13:23) [186]

to Игорь Шевченко ©   (12.03.07 13:11) [185]:
Согласен. Но он, вообще говоря, написал, зачем это было сделано именно так, и что это временное явление.


 
euru ©   (2007-03-12 13:25) [187]


> Игорь Шевченко ©   (12.03.07 13:11) [185]
Была бы возможность использовать в хелперах поля, таких способов реализации было бы меньше.


 
euru ©   (2007-03-12 13:30) [188]


> Игорь Шевченко ©   (12.03.07 12:47) [183]
Ну так здесь, скорее всего, проблема в распределении своего времени, а не в хелперах. На изучение документации VCL ведь тоже было потрачено какое-то время.


 
vuk ©   (2007-03-12 13:42) [189]

to euru ©   (12.03.07 13:25) [187]:
>Была бы возможность использовать в хелперах поля, таких способов
>реализации было бы меньше.
Такой возможности нет и не будет. По причине того, что у хелпера нет экземпляров.


 
Игорь Шевченко ©   (2007-03-12 13:43) [190]

euru ©   (12.03.07 13:30) [188]

VCL как раз понятна, так что изучается довольно легко.


 
euru ©   (2007-03-12 14:02) [191]


> vuk ©   (12.03.07 13:42) [189]
Но ведь компилятор-то знает, что это хелпер. Вот и выдавал бы синтаксическую ошибку при использовании хелпера вне контекста класса.


 
euru ©   (2007-03-12 14:05) [192]


> Игорь Шевченко ©   (12.03.07 13:43) [190]
Могу я это понимать как утверждение, что только VCL понятна и легкоизучаема?


 
Игорь Шевченко ©   (2007-03-12 14:13) [193]

euru ©   (12.03.07 14:05) [192]

Нет, почему же. Могу еще RxLib привести в качестве легко понятной и изучаемой библиотеки. Но, к сожалению, непонятного кода намного больше.


 
Kolan ©   (2007-03-12 14:17) [194]

Раз тут про хелперы... Вот я крутил Delphi for Don net. Там такая штука кидаешь допустем ToolTip и он появляется на всех контролах. Это тоже с пом хелперов сделано? А как? Пробовал - неполучилось...

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


 
euru ©   (2007-03-12 14:30) [195]


> Игорь Шевченко ©   (12.03.07 14:13) [193]
Т.е. можно утверждать, что сторонние разработчики также способны создавать понятный код, требующий минимального усилия для его изучения?


> Но, к сожалению, непонятного кода намного больше.
К сожалению, любых вещей, создаваемых дилетантами, всегда намного больше.


 
Игорь Шевченко ©   (2007-03-12 14:37) [196]

euru ©   (12.03.07 14:30) [195]


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


Безусловно.


> К сожалению, любых вещей, создаваемых дилетантами, всегда
> намного больше.


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

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


 
euru ©   (2007-03-12 15:00) [197]


> Игорь Шевченко ©   (12.03.07 14:37) [196]
А раз имеются разработчики, пишущие понятный код без хелперов, почему же тогда не может быть разработчиков, которые могут писать понятный код с использованием хелперов?


> К сожалению, я зарабатываю на хлеб, взаимодействуя с кодом,
>  написанным в том числе и дилетантами.
Но ведь не у всех входит в обязанности изучать такой код. Остальным-то зачем отказываться от профессионально написанных библиотек, в которых используются хелперы.


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


 
Игорь Шевченко ©   (2007-03-12 15:04) [198]

euru ©   (12.03.07 15:00) [197]


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


Я вообще-то высказал свое мнение, исходя из собственных реалий.

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

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

Однако отчего ж народ высказывает негативное мнение ?


 
euru ©   (2007-03-12 15:25) [199]


> Игорь Шевченко ©   (12.03.07 15:04) [198]
> Однако отчего ж народ высказывает негативное мнение ?
Чаще всего потому что это популярное мнение. Либо изначально не разобрался в его правильном применении, получил негативный опыт, выработал негативный условный рефлекс.

Ни один из перечисленных примеров у меня не вызывает негатива. Как там про овощ, место и пользу? :)


 
Игорь Шевченко ©   (2007-03-12 15:46) [200]

euru ©   (12.03.07 15:25) [199]

Про овощ все хорошо. Собственно, иллюстрация овоща не ко времени и была в примерах с Memo.Lines.DoWork

А при скрещивании System.Object и TObject helper"ы, как и овощи вполне себе приносят пользу.


 
euru ©   (2007-03-12 15:56) [201]


> Игорь Шевченко ©   (12.03.07 15:46) [200]
Ну так если хелперы приносят пользу, будучи правильно применёнными, зачем же тогда от них отказываться?

Может, лучше тогда стоит отказываться от разработок, где они (по субъективному мнению оценивающего код) не несут никакой пользы?


 
Игорь Шевченко ©   (2007-03-12 15:59) [202]

euru ©   (12.03.07 15:56) [201]


> Может, лучше тогда стоит отказываться от разработок, где
> они (по субъективному мнению оценивающего код) не несут
> никакой пользы?


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


 
euru ©   (2007-03-12 16:29) [203]


> Игорь Шевченко ©   (12.03.07 15:59) [202]
Могу ли я сделать вывод, что мы пришли к взаимопониманию в отношении использования хелперов?
А именно. Хелперы - один из элементов синтаксиса языка программирования, сам по себе никак не влияющий на качество написания программ. Качество программ зависит от разработчика, применяющего эти хелперы (впрочем, как и другие возможности языка), а по их наличию в исходном коде ещё нельзя судить о квалифицированности специалиста.


 
Игорь Шевченко ©   (2007-03-12 16:34) [204]

euru ©   (12.03.07 16:29) [203]

Да, конечно. То, что хелперы являюся элементом языка, это факт, от него никуда не деться. То, что качество программ зависит от разработчика, это тоже аксиома. С последним пунктом сложно согласиться/не согласиться, потому что о квалифицированности разработчика можно судить по применению иных элементов синтаксиса. То же самое относится к множественному наследованию, макросам и оператору goto :)


 
euru ©   (2007-03-12 16:53) [205]


> Игорь Шевченко ©   (12.03.07 16:34) [204]
А как же

> Игорь Шевченко ©   (09.03.07 21:06) [96]
> Кстати, в случае DB-Aware controls неплохо бы на мой взгляд
> подошло  множественное наследование
Вот встретится такое в твоём коде, и как тогда судить о квалификации? Или это время от времени вырывающиеся наружу пороки, с которыми идёт постоянная борьба? :)


 
GrayFace ©   (2007-03-12 17:48) [206]

> http://hallvards.blogspot.com/
Чем только люди не страдают...


 
Суслик ©   (2007-03-12 19:40) [207]


> [206] GrayFace ©   (12.03.07 17:48)
> > http://hallvards.blogspot.com/
> Чем только люди не страдают...

Почему? Ты имеешь что-то против?
Он что-то неверно написал? Может покажешь где (не имеются в виду опечатки)?


 
Суслик ©   (2007-03-12 19:44) [208]

да... блин, а идея то благая была, блог завести.
даже мотивации нет что-то еще писать.


 
Суслик ©   (2007-03-12 19:51) [209]

блин, да что за ерунда с теорией понятного кода - понятный код, это твой код.

все. весь другой код априори непонятен, пока с ним не разберешься.

тут кто-то про vcl упоминал - мол какая она понятная. конечно понятная, если разобраться. если надо, то я действтиельно, могу разобраться с тем или иным вопросом - но говорить о понятности не приходится, ибо все равно приходится разбираться.

ну а кому она понятна с первого взгляда, то... не пойму я почему такие таланты за 10^6 уе не продаются?

ЗЫ
без обид - я привел мой личный опыт понятного когда.


 
GrayFace ©   (2007-03-12 21:18) [210]

ТЮзер (в нете через паяльник)   (11.03.07 23:13) [157]
Читаю, читаю, .... Кто-нибудь может привести примитивный пример, что такое эти хелперы, и где они удобны? У меня семерка.

Например, я бы сделал TObjectHelper  function GetSelf  Result:=self
Полезно будет в конструкции with. Чтобы не заводить переменную, а писать
with TMyObject do
  try
    DoSomething(GetSelf);
  finally
  end;


Суслик ©   (12.03.07 19:40) [207]
> [206] GrayFace ©   (12.03.07 17:48)
> > http://hallvards.blogspot.com/
> Чем только люди не страдают...

Почему? Ты имеешь что-то против?

Как так понял, все это ради того чтобы не писать наследник формы. Не понятно, в чем смысл.
Если же это действительно надо, то написали бы наследник, сняли с класса TForm/TCustomForm защиту от записи, изменили бы ссылку на таблицу свойств, пропатчили код TObject.NewInstance и FreeInstance, выделяли бы в нем доп. место под свои переменные либо заменили бы MemoryManager и делали это в нем. Все равно все это криво, но хоть меньше гмеорроя было бы.

Суслик ©   (12.03.07 19:44) [208]
да... блин, а идея то благая была, блог завести.
даже мотивации нет что-то еще писать.

А че? Давай пиши исчо, вон как хорошо пофлудили!

P.S. В "Delphi 2007 (часть I)" несколько раз "знаю" вместо "знают"


 
Суслик ©   (2007-03-12 21:45) [211]


> P.S. В "Delphi 2007 (часть I)" несколько раз "знаю" вместо
> "знают"

да я не славлюсь аккуратностью


 
oxffff ©   (2007-03-12 22:03) [212]


> Как так понял, все это ради того чтобы не писать наследник
> формы. Не понятно, в чем смысл.
> Если же это действительно надо, то написали бы наследник,
>  сняли с класса TForm/TCustomForm защиту от записи, изменили
> бы ссылку на таблицу свойств, пропатчили код TObject.NewInstance
> и FreeInstance, выделяли бы в нем доп. место под свои переменные
> либо заменили бы MemoryManager и делали это в нем. Все равно
> все это криво, но хоть меньше гмеорроя было бы.


Можно их не трогать

Virtual method table layout
-40 Cardinal instance size in bytes

Но видимо не все так просто.


 
GrayFace ©   (2007-03-12 23:02) [213]

Начинаю понимать, в чем дело, но не понятно, зачем понадобилось переменную затирать.


 
GrayFace ©   (2007-03-12 23:12) [214]

oxffff ©   (12.03.07 22:03) [212]
Но видимо не все так просто.

Да, им было нужно чтоб интерфейс класса не менялся, т.к. иначе класс считается измененным и старые .dcu-шки не работают.


 
Игорь Шевченко ©   (2007-03-12 23:47) [215]


> блин, да что за ерунда с теорией понятного кода - понятный
> код, это твой код.


Опыт дело наживное


> тут кто-то про vcl упоминал - мол какая она понятная. конечно
> понятная, если разобраться. если надо, то я действтиельно,
>  могу разобраться с тем или иным вопросом - но говорить
> о понятности не приходится, ибо все равно приходится разбираться


Я упоминал. Понятная. Ты в коде VCL видишь какие-то непонятные места ? Берешь и читаешь, не испытывая дискомфорта.

Еще пример понятного кода - это "hello, world" на С


 
euru ©   (2007-03-13 01:06) [216]

Может, не будем по второму кругу обсуждать полезность/бесполезность хелперов и их влияние на понимание и удобочитаемость кода? Вроде бы в [203] и [204] уже выяснили. :)

Кстати, "hello, world" на С сиспользованием WinAPI не таким уж и понятным выглядит при первом знакомстве.


> Суслик
А чем вызвано отсутствие полей в хелперах? Ведь согласно парадигме ООП данные и методы их обработки равноправны. Они составляют единое целое в классе. А в хелперах, являющихся составной частью класса, наблюдается явная дискриминация данных.


 
oxffff ©   (2007-03-13 09:55) [217]


> А в хелперах, являющихся составной частью класса, наблюдается
> явная дискриминация данных.


По сути helper это набор external процедур и функций с неявным параметром object instance.
Абстракции данных он не порождает.


 
euru ©   (2007-03-13 11:21) [218]


> oxffff ©   (13.03.07 09:55) [217]
Вот мне и интересно. Почему хелпер не может расширять абстракции данных? Какие могут возникнуть противоречия?


 
oxffff ©   (2007-03-13 11:43) [219]


> расширять абстракции данных?


Это наследование.

class поля - теже глобальные переменные с ограниченным scope.


 
euru ©   (2007-03-13 11:55) [220]


> oxffff ©   (13.03.07 11:43) [219]
Наследование - это создание нового класса, а хелпер - это внедрение в имеющийся класс. Это два разных способа расширения функциональности. Почему же тогда при наследовании возможно добавление данных, а при использовании хелперов - нельзя?

Ещё вопрос. Если хелпер добавить к классу, у которого есть потомки, появится ли у потомков методы хелпера?


 
GrayFace ©   (2007-03-13 12:49) [221]

> А чем вызвано отсутствие полей в хелперах? Ведь согласно
> парадигме ООП данные и методы их обработки равноправны.
> Они составляют единое целое в классе. А в хелперах, являющихся
> составной частью класса, наблюдается явная дискриминация
> данных.

Суть не в парадигме, а в громоздкости реализации.

> Если хелпер добавить к классу, у которого есть потомки, появится ли у потомков методы хелпера?

Определенно да, т.к. имеются хелперы к TObject и TCustomForm, которые иначе не было бы возможности толком использовать. (сам не разу не использовал Delphi выше 7)


 
oxffff ©   (2007-03-13 13:04) [222]

>Ещё вопрос. Если хелпер добавить к классу, у которого есть потомки, >появится ли у потомков методы хелпера?

A class helper is a type that - when associated with another class - introduces additional method names and properties which may be used in the context of the associated class (or its descendants).

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

A class helper simply introduces a wider scope for the compiler to use when resolving identifiers.


 
jack128 ©   (2007-03-13 13:23) [223]

GrayFace ©   (12.03.07 23:12) [214]
т.к. иначе класс считается измененным и старые .dcu-шки не работают.

а зачем нужно чтоб старые дкушки читались?  Вроде раньше на это забивали


 
vuk ©   (2007-03-13 13:34) [224]

to jack128 ©   (13.03.07 13:23) [223]:
>а зачем нужно чтоб старые дкушки читались?  Вроде раньше на это
>забивали
Эти меры предприняты только для D2007, хотели оставить бинарную совместимость dcu т.к. версия компилятора, как я понял, та же самая будет. Если совместимости не будет, это может повлиять на тех, кто использует коммерческие компоненты без исходников.

Я понял, что извращения с хелпером и фиктивными свойствами будут убраны в хайландере. Там уже будет и новая версия компилятора. И бинарной совместимости не будет.


 
euru ©   (2007-03-13 16:38) [225]


> GrayFace ©   (13.03.07 12:49) [221]
> Суть не в парадигме, а в громоздкости реализации.
Т.е. добавление полей в хелперы сильно увеличивает громоздкость реализации по сравнению с реализацией хелперов только с методами? Почему?


 
jack128 ©   (2007-03-13 16:48) [226]

euru ©   (13.03.07 16:38) [225]
Т.е. добавление полей в хелперы сильно увеличивает громоздкость реализации по сравнению с реализацией хелперов только с методами? Почему?

Насколько я понимаю основная сложность будет с рантайм пакетами.


 
vuk ©   (2007-03-13 19:16) [227]

to euru ©   (13.03.07 16:38) [225]:
>Т.е. добавление полей в хелперы сильно увеличивает громоздкость
>реализации по сравнению с реализацией хелперов только с методами?
>Почему?
Уже кажется несколько раз повторялось. У хелперов нет экземпляров и, соответственно, места для хранения данных.


 
euru ©   (2007-03-13 23:59) [228]


> vuk ©   (13.03.07 19:16) [227]
Я давно уже понял, что имеющаяся реализация хелперов в Delphi не предусматривает в них наличие полей. Просто мне пока непонятна, в чём принципиальная невозможность такой реализации.

Отсутствие у хелперов экземпляров, как мне кажется, не аргумент. Можно просто запретить объявление переменных с хелперными типами ещё при компиляции выдачей сообщения о синтаксической ошибке.


 
vuk ©   (2007-03-14 00:21) [229]

to euru ©   (13.03.07 23:59) [228]:
>Просто мне пока непонятна, в чём принципиальная невозможность такой
>реализации.
Экземпляр, он, по идее, монолитен должен быть. А хелперы применяться к одному и тому же экземпляру могут разные, в зависимости от контекста.

>Можно просто запретить объявление переменных с хелперными типами ещё
>при компиляции выдачей сообщения о синтаксической ошибке.
Не понял, это-то здесь при чем?


 
euru ©   (2007-03-14 00:47) [230]


> vuk ©   (14.03.07 00:21) [229]
> Экземпляр, он, по идее, монолитен должен быть.
Но ведь при создании экземпляра класса у компилятора уже есть информация о применённых к этому классу хелперов. А значит, при выделении памяти под экземпляр класса можно учесть поля хелперов. А с другой стороны, почему экземпляр должен быть монолитен?


> Не понял, это-то здесь при чем?
Да, как-то я не так написал. Попробую по-другому. :)
Нужно просто запретить создание экземпляров хелперных типов. Они должны существовать только в контексте класса. Примерная аналогия - интерфейсы. Их реализация тоже не может существовать вне класса.


 
vuk ©   (2007-03-14 00:54) [231]

to euru ©   (14.03.07 00:47) [230]:
>Но ведь при создании экземпляра класса у компилятора уже есть
>информация о применённых к этому классу хелперов.
Откуда бы?

>А с другой стороны, почему экземпляр должен быть монолитен?
Ну как-то принято так... :)

>Нужно просто запретить создание экземпляров хелперных типов.
Ну так их и нет. Зачем что-то еще запрещать?


 
jack128 ©   (2007-03-14 22:27) [232]

euru ©   (14.03.07 0:47) [230]
есть TObjectHelper = class helper for Tobject
 Ffield: Integer;
end;
есть рантайм пакет собранный БЕЗ этого хелпера.  Есть exe, юзающее этот пакет и этот хелпер.  И как??


 
euru ©   (2007-03-15 00:11) [233]


> vuk ©   (14.03.07 00:54) [231]

> Откуда бы?
Либо хелпер объявлен в текущем модуле, либо в разделе uses указан модуль, в которомобъявлен хелпер. Разве компилятору недостаточно информации?


> Ну как-то принято так... :)
Согласись, что это не является веским аргументом в пользу монолитного выделения памяти под объекты. :)


> Ну так их и нет. Зачем что-то еще запрещать?
Прекрасно. Т.е. одно из условий наличия хеперов с полями соблюдены. Что ещё мешает из появлению в языке?


> jack128 ©   (14.03.07 22:27) [232]
А зачем рантайм пакету знать о расширенных возможностях класса? Внутри пакета они всё равно не используются.

Если я, например, создам потомка от класса, имеющегося в пакете, неужели пакет не сможет работать с экземплярами моего потомка?


 
vuk ©   (2007-03-15 00:28) [234]

to euru ©   (15.03.07 00:11) [233]:
>Либо хелпер объявлен в текущем модуле, либо в разделе uses указан
>модуль, в которомобъявлен хелпер.
А если так: экземпляр по цепочке вызовов передается невесть куда в пакет (например динамически загруженный) и уже там на него навешивается хелпер. Что делать-то?

>Согласись, что это не является веским аргументом в пользу монолитного
>выделения памяти под объекты. :)
А скорость доступа к данным является аргументом?


 
jack128 ©   (2007-03-15 01:46) [235]

euru ©   (15.03.07 0:11) [233]
А зачем рантайм пакету знать о расширенных возможностях класса?

затем, что раз есть в хелпере есть поле, то оно должно быть во всех классах.  В том числе и тех, что были созданы кодом внутри пакета.
PS Я не говорю, что поля в хелпере невозможно реализовать. Все можно. Но цена - весьма высока.


 
jack128 ©   (2007-03-15 01:48) [236]

vuk ©   (15.03.07 0:28) [234]
А если так: экземпляр по цепочке вызовов передается невесть куда в пакет (например динамически загруженный) и уже там на него навешивается хелпер. Что делать-то?


Ну да.  Собственно я об этом же.


 
euru ©   (2007-03-15 11:19) [237]


> vuk ©   (15.03.07 00:28) [234]


> А если так: экземпляр по цепочке вызовов передается невесть
> куда в пакет (например динамически загруженный) и уже там
> на него навешивается хелпер. Что делать-то?
Встречный вопрос. Экземпляр по цепочке вызовов передаётся невесть куда в пакет (например, динамически загруженный), в котором используется потомок класса данного экземпляра. Что произойдёт в таком случае?


> А скорость доступа к данным является аргументом?
А какая прямая связь между синтаксисом языка и техническими характеристиками вычислительной техники?


> jack128 ©   (15.03.07 01:46) [235]


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


 
jack128 ©   (2007-03-15 15:55) [238]

euru ©   (15.03.07 11:19) [237]
что такие же поля должны появится и у предков этого класса.

Не должны. Но есть поле появится к хелпере к TObject, то поле должно появиться во всех объектах.


 
jack128 ©   (2007-03-15 15:58) [239]

euru ©   (15.03.07 11:19) [237]
Встречный вопрос. Экземпляр по цепочке вызовов передаётся невесть куда в пакет (например, динамически загруженный), в котором используется потомок класса данного экземпляра. Что произойдёт в таком случае?

а что должно произойти?  Ну используется и используется.
jack128 ©   (15.03.07 15:55) [238]
Но ЕСЛИ поле появится к хелпере


 
GrayFace ©   (2007-03-15 17:17) [240]

euru ©   (13.03.07 16:38) [225]
Т.е. добавление полей в хелперы сильно увеличивает громоздкость реализации по сравнению с реализацией хелперов только с методами? Почему?

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

Пусть в хелперах будут поля, у класса будет некий объем памяти, отведенный под хелперы. Дальше надо каждому хелперу дать смещение его данных относительно начала этого объема.
- Если это зашить в код, то сутуация: 2 пакета, в обоих по хелперу к одному и тому же классу. Оба пакета знают только о своих хелперах, значит у обоих смещение данных хелпера будет 0.
- Значит надо создавать переменную со смещением хелпера, при компиляции и дин. загрузке пакета ее заполнять и при каждом вызове метода хелпера к ней обращаться.
Теперь как можно добавить сам объем.
- Для каждого класса нужна будет переменная с размером этого блока. Опять же должна будет зполняться при динамической зарузке или компилянии программы.
Теперь возникают проблемы с самим заполнением этих переменных. Хотя вроде решаемо, придется менять vmt*, менять NewInstance, InitInstance, но вроде возможно.

Но виртуальные функции переопределять хелперам уж точно не получится, применение хелперов по-прежнему будет редким, соответственно возникает вопрос - нафига?


 
euru ©   (2007-03-16 01:22) [241]

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

1. Создадим модуль, содержащий класс, к которому в дальнейшем присоединим хелпер.
unit u1;

interface

type
  TA = class
  end;

implementation
end.


2. Создадим модуль, содержащий хелпер к этому классу.
unit u2;

interface

uses u1;

type
  TB = class helper for TA
    Field: Integer;
    procedure DoWork();
  end;

implementation
end.


3. Создадим модуль, использующий класс с хелпером.
unit u3;

interface

uses u1, u2;

procedure SetField(a: TA; value: Integer);

implementation

procedure SetField(a: TA; value: Integer);
begin
  a.Field := value;
end;

end.


Теперь напишем программу, в которой якобы может возникнуть коллизия.
program p1;

uses u1, u3;

var a: TA;

begin
  a := TA.Create();
  SetField(a, 5);
end;


Модуль u2, содержащий хелпер, в программе необъявлен. Но это не помешает компилятору учесть наличие хелпера в классе, потому что его присутсятвие определяется косвенно через модуль u3, в котором есть ссылка модуль u2, содержащий хелпер.


 
euru ©   (2007-03-16 01:35) [242]


> GrayFace ©   (15.03.07 17:17) [240]
Соглашусь, что реализация хелперов с полями будет сложнее реализации без них. Правда, пока не уверен, что она будет выглядить так громоздко.

Но пока меня интересует другой вопрос. Возможна ли в принципе реализация хелперов с полями?


> Но виртуальные функции переопределять хелперам уж точно
> не получится
Однозначно?


 
jack128 ©   (2007-03-16 01:52) [243]

euru ©   (16.03.07 1:22) [241]
Гм. Такое очущение, что ты не читал, то что написал vuk и я.  Пока дело какается монолитной программы - вопросов нету. Проблемы возникнут, когда используются ран тайм пакеты.


 
GrayFace ©   (2007-03-16 16:22) [244]

euru ©   (16.03.07 1:35) [242]
Соглашусь, что реализация хелперов с полями будет сложнее реализации без них. Правда, пока не уверен, что она будет выглядить так громоздко.

А я уверен, что она будет выглядеть более громоздко.


 
Суслик ©   (2007-03-16 16:34) [245]


> [243] jack128 ©   (16.03.07 01:52)
> euru ©   (16.03.07 1:22) [241]
> Гм. Такое очущение, что ты не читал, то что написал vuk
> и я.  Пока дело какается монолитной программы - вопросов
> нету. Проблемы возникнут, когда используются ран тайм пакеты.

уж прости :) сам люблю опечатки, но у тебя получилось офигительней моих в 100 раз :)


 
jack128 ©   (2007-03-16 21:15) [246]

Суслик ©   (16.03.07 16:34) [245]
но у тебя получилось офигительней моих в 100 раз :)

Ну дык!  Стараемся.  Растём над собой, так сказать ;-)


 
euru ©   (2007-03-19 02:26) [247]


> jack128 ©   (16.03.07 01:52) [243]
> Такое очущение, что ты не читал, то что написал vuk и я.
Почему не читал? Читал. Но ведь это просто предположение, ничем не подтверждённое. С таким же успехом я могу утверждать, что не будет никаких проблем с использованием хелперов в динамически загруженных пакетах. В пользу своего утверждения я привёл пример. В ответ не получил ни указаний ошибок в моих рассуждениях, ни контрпримеров, доказывающих ваши утверждения.


> vuk ©   (15.03.07 00:28) [234]
> А если так: экземпляр по цепочке вызовов передается невесть
> куда в пакет (например динамически загруженный) и уже там
> на него навешивается хелпер. Что делать-то?
Насколько я понимаю, может быть две ситуации.
1. В программе создаётся хелпер для класса, объявленного в пакете. Использование объектов такого класса с хелпером в самой программе проблем не вызовет (см. [241]). Передача таких объектов в пакет тоже ни к чему криминальному не приведёт. В пакет передастся только та часть объекта, которая используется в пакете. А как с ней работать, пакет знает.

2. Хелпер для типа, используемого в программе, создаётся в пакете. Если я не ошибаюсь, для организации взаимодействия с пакетом создаётся модуль, в котором описывается интерфейс этого пакета. Если описание сделано корректно, то компилятору будет известна информация о наличие хелпера в пакете, и он учтёт её при создании объектов.


> А скорость доступа к данным является аргументом?
Нет. К языку программирования он никакого отношения не имеет.


> jack128 ©   (15.03.07 01:46) [235]
> затем, что раз есть в хелпере есть поле, то оно должно быть
> во всех классах.  В том числе и тех, что были созданы кодом
> внутри пакета.
А если я перефразирую так: раз в потомке есть поле (класс с хелпером фактически является потомком оригинального класса), то оно должно быть во всех классах. В том числе и в его предках (оригинальный класс в пакете фактически является предком для класса с хелпером в программе).
Это будет правильным утверждением?


 
euru ©   (2007-03-19 02:46) [248]


> GrayFace ©   (15.03.07 17:17) [240]
А если так.
Класс знает список всех добавленных когда-либо к нему хелперов. При создании объекта у него заполняется список только тех хелперов, которые реально использовались для этого объекта.

Теперь обращение к элементам хелпера объекта приведёт к следующим шагам:
1. Поиск идентификатора хелпера среди всех хелперов класса.
2. Поиск найденного идентификатора хелпера среди хелперов объекта.
3. Если такой идентификатор у объекта не найден, то выдать сообщение об ошибке.
4. Если хелпер у объекта есть, то взять идентификатор этого хелпера в объекте.
5. Адрес к данным объекта, добавленным хелпером, найти в таблице на пересечении идентификаторов хелпера класса и объекта.


> Но виртуальные функции переопределять хелперам уж точно
> не получится
А, например, подменить в vmt адрес виртуальной функции класса адресом функции хелпера?


 
GrayFace ©   (2007-03-19 20:32) [249]

euru ©   (19.03.07 2:26) [247]
В пользу своего утверждения я привёл пример.

Где??

euru ©   (19.03.07 2:26) [247]
класс с хелпером фактически является потомком оригинального класса

Теперь все ясно, ты ничего не понял о хелперах. Хелпер динамически подключается к классу, в том числе к классу из пакета. Пакет не будет сам по себе создавать объекты "класса с хелпером".

euru ©   (19.03.07 2:46) [248]
3. Если такой идентификатор у объекта не найден, то выдать сообщение об ошибке.

Т.е. при любой попытке использовать хелпер будет ошибка? А то кто ж добавит его идентификатор к хелперам объекта?

euru ©   (19.03.07 2:46) [248]
5. Адрес к данным объекта, добавленным хелпером, найти в таблице на пересечении идентификаторов хелпера класса и объекта.

3D таблица со всеми хелперами, классами и объектами? :)))

euru ©   (19.03.07 2:46) [248]
А, например, подменить в vmt адрес виртуальной функции класса адресом функции хелпера?

А как определить, кто из хелперов "главнее"?


 
jack128 ©   (2007-03-20 01:56) [250]

euru ©   (19.03.07 2:26) [247]
раз в потомке есть поле (класс с хелпером фактически является потомком оригинального класса

нет, класс с хелпером - это не потомок класса.
euru ©   (19.03.07 2:26) [247]
раз в потомке есть поле , то оно должно быть во всех классах.

Что за бред???

Вообще ПРИНЦИПИАЛЬНО реализовать, то что ты хочешь - можно.  Но на практиче - это с одной стороны будет весьма сложно для  разработчиков компилятора, с другой - доступ к этим полям будет весьма и весьма тормознутым. Короче - нафиг надо.  Кому это реально нужно, те без проблем смогут сами все это реализовать, благо в дельфе все для этого есть.


 
euru ©   (2007-03-20 15:26) [251]


> GrayFace ©   (19.03.07 20:32) [249]

> Где??
Здесь - [241].


> Теперь все ясно, ты ничего не понял о хелперах.
О каких хелперах? Которые в Delphi? Так о них вроде бы уже всё выяснили. Я же о других хелперах говорю. Тех, которые добавляют к классу не только методы, но и поля. А это явно не просто динамическая привязка методов хелпера к классу.


> Пакет не будет сам по себе создавать объекты "класса с хелпером".
А вот товарищи vuk и jack128 считают иначе - см. [234] и [235].


> Т.е. при любой попытке использовать хелпер будет ошибка?
>  А то кто ж добавит его идентификатор к хелперам объекта?
Компилятор обладает всей необходимой информацией, которая позволит ему правильно инициализировать список хелперов объекта при его создании.


> 3D таблица со всеми хелперами, классами и объектами? :)))
А 2D-таблица vmt со всеми классами и методами улыбки не вызывает?


> А как определить, кто из хелперов "главнее"?
А зачем? Совпадение сигнатуры методов вызовет сообщение об ошибке ещё во время компиляции.

--------------------------------------------------------------------


> jack128 ©   (20.03.07 01:56) [250]



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


> Что за бред???
А требование наличия хелперов во всех пакетах, даже там, где они изначально не были предусмотрены, не бред?


> Вообще ПРИНЦИПИАЛЬНО реализовать, то что ты хочешь - можно.
>   Но на практиче - это с одной стороны будет весьма сложно
> для  разработчиков компилятора, с другой - доступ к этим
> полям будет весьма и весьма тормознутым. Короче - нафиг
> надо.
Чем-то напоминает утверждения 15-20-летней давности о необходимости в языках средств ООП.


> Кому это реально нужно, те без проблем смогут сами все это
> реализовать, благо в дельфе все для этого есть.
А вот можно увидеть пример текущей дельфийской реализации хелперов в Delphi 7 и ниже средствами самого языка? И если это действительно можно, то зачем тогда они были введены?


 
GrayFace ©   (2007-03-23 21:57) [252]

euru ©   (20.03.07 15:26) [251]
Здесь - [241].

Это ж не кусок реализации. Даже не пример когда это нужно.

euru ©   (20.03.07 15:26) [251]
А вот товарищи vuk и jack128 считают иначе - см. [234] и [235].

Нет, так же.

jack128 ©   (20.03.07 1:56) [250]
Но на практиче - это с одной стороны будет весьма сложно для  разработчиков компилятора, с другой - доступ к этим полям будет весьма и весьма тормознутым.

Думаю, можно сделать и без особых временных затрат на доступ, но проблем по горло.

euru ©   (20.03.07 15:26) [251]
А 2D-таблица vmt со всеми классами и методами улыбки не вызывает?

Конечно нет. Объектов могут быть тысячи.

euru ©   (20.03.07 15:26) [251]
А зачем? Совпадение сигнатуры методов вызовет сообщение об ошибке ещё во время компиляции.

Пакеты компилируются отдельно друг от друга и могут подключаться к программе динамически.

euru ©   (20.03.07 15:26) [251]
С точки зрения разработчика - не потомок. Программист продолжает использовать тот же класс, что и раньше. Просто у класса появились новые поля и методы. С точки зрения компилятора - потомок. Новую функциональность нельзя просто механически приписать к текущему классу. Хотя бы потому, что в разных модулях могут объявляться разные хелперы к одному и тому же классу. И для контроля правильности их использования компилятору нужно будет как-то их различать. А это можно сделать, создав, например, потомков (недоступных разработчику) от оригинального класса для всех используемых вариантов с хелперами.

Ну вот ты сам сказал, что хелперы с полями невозможны (хотя это не совсем так) или будут непонятно чем. См. то что выделено жирным. Объект может создаваться в одном пакете, а в другом - использоваться хелпер к такому же классу. В твоей схеме в этом случае велетит ошибка? Тогда скажи, зачем программист будет писать хелперы к своим классам, вместо того чтобы создать потомка? Ведь для чужих пакетов он хелперов написать не сможет.


 
euru ©   (2007-03-25 03:39) [253]


> GrayFace ©   (23.03.07 21:57) [252]
> Тогда скажи, зачем программист будет писать хелперы к своим
> классам, вместо того чтобы создать потомка?
Думаю, это основной вопрос.

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

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

Примеры применения (на примере VCL) таких классов я уже приводил выше, но повторю их ещё раз:
1. Поле PasswordChar в классе TEdit. Очень редко используемое поле. Вынеся его во вспомогательный класс можно было бы добавлять это поле (и соответствующее поведение) только к тем объектам TEdit, которым оно действительно нужно.
2. Свойство Dockable у класса TControl. Тоже не для всех контролов и не во всех проектах используется. Также можно вынести в отдельный класс и подключать по мере необходимости.
3. Дублирование обычных контролов и DB-контролов. DB-функциональность можно было бы вынести в отдельный вспомогательный класс и подключать его к нужным обычным контролам.

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

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

P.S.: Кстати, кроме наследования (вертикального связывания классов) существует ещё и горизонтальное связывание, реализуемое в аспектно-ориентированных языках. Спасибо vuk"у, который в соё время дал ссылки на такие языки. В сравнении с этими способами связывания хелперы можно назвать внутренним связыванием, реализующим саморазвитие классов.



Страницы: 1 2 3 4 5 6 7 вся ветка

Форум: "Прочее";
Текущий архив: 2007.04.22;
Скачать: [xml.tar.bz2];

Наверх





Память: 1.33 MB
Время: 0.051 c
3-1170253237
O.O
2007-01-31 17:20
2007.04.22
Пользователи и пароли в FireBird


15-1174994817
svbti
2007-03-27 15:26
2007.04.22
Проверка XML-файла


2-1175244701
YadlU
2007-03-30 12:51
2007.04.22
Преобразование Даты в Число


1-1172750179
S@shka
2007-03-01 14:56
2007.04.22
Диспетчер задач / Память процесса


15-1174675545
VirEx
2007-03-23 21:45
2007.04.22
подскажите компонент локальной базы данных





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский