| 
| 
 | Вопрос # 3 062/ вопрос открыт / | 
 |  Приветствую, уважаемые эксперты!У меня такая проблема: я первый раз пытаюсь написать компонент (а вместе с ним и новый класс с конструктором), почитал несколько статей по созданию компонентов, так же почитал про классы. Решил для начала создать легкий компонент, который управляет лог-файлом.  Вот основные проблемы:
 
 1) При компиляции выдается ошибка:
 
 [Error] LogMaster.pas(21): Declaration of 'Create' differs from previous declaration (код в приложении), в чем тут дело?
 
 2) немогли бы вы по подробней рассказать когда следует использовать override, overload?
 Приложение:Переключить в обычный режим unit LogMaster; interface uses  SysUtils, Classes, Forms; type  TLogMaster = class(TComponent)   procedure AddEvent(Event: string);   function RemoveLog: boolean;  private    LogFile: text;    T: string;    { Private declarations }  protected    { Protected declarations }  public    { Public declarations }  published    constructor Create(FileName: string); override;    { Published declarations }  end; procedure Register; implementation procedure Register;begin  RegisterComponents('Log Master', [TLogMaster]);end; constructor TLogMaster.Create(FileName: string);var D: string;begin  D:=DateToStr(Now);  T:=TimeToStr(Now);  FileName:=FileName+'_log.txt';  AssignFile(LogFile, FileName);  try   Rewrite(LogFile);   Write(LogFile,'------ File info -----'+#13#10);   Write(LogFile,'## Log File From "'+ExtractFileName(Application.ExeName)+'"'+#13#10);   Write(LogFile,'## Start Date: '+D+#13#10);   Write(LogFile,'## Start Time: '+T+#13#10);    Write(LogFile,'------ Start Log -----'+#13#10+#13#10+#13#10);   CloseFile(LogFile);  except  end;end; procedure TLogMaster.AddEvent(Event: string);begin try  Append(LogFile);  Write(LogFile,T+': '+Event+#13#10); except end;end; function TLogMaster.RemoveLog: boolean;beginend; end.
|  |   Вопрос задал: IlluminatI (статус: 2-ой класс)Вопрос отправлен: 3 августа 2009, 21:19
 Состояние вопроса: открыт, ответов: 3.
 |  Ответ #1. Отвечает эксперт: min@y™ Как говорится, найди 10 отличий и тогда всё поймёшь.
 Какой смысл делать такой класс компонентом?
 Приложение:Переключить в обычный режим unit LogMaster; interface uses  SysUtils, Classes, Forms; type  TLogMaster = class(TComponent)   procedure AddEvent(Event: string);   function RemoveLog: boolean;  private    LogFile: text;    T: string;   protected    { Protected declarations }  public    { Public declarations }  published    constructor Create(AOwner: TComponent; const FileName: string); reintroduce;   end; procedure Register; implementation procedure Register;begin  RegisterComponents('Log Master', [TLogMaster]);end; constructor TLogMaster.Create(AOwner: TComponent; const FileName: string);var D: string;begin  inherited Create(AOwner);   D:=DateToStr(Now);  T:=TimeToStr(Now);      AssignFile(LogFile, FFileName);{$I-}  Rewrite(LogFile);  Write(LogFile,'------ File info -----' + #13#10);  Write(LogFile,'## Log File From "' + ExtractFileName(Application.ExeName)+'"'+#13#10);  Write(LogFile,'## Start Date: ' + D + #13#10);  Write(LogFile,'## Start Time: ' + T + #13#10);   Write(LogFile,'------ Start Log -----'+#13#10+#13#10+#13#10);  CloseFile(LogFile);{$I+}  if IOError <> 0    then raise;end; procedure TLogMaster.AddEvent(Event: string);begin try  Append(LogFile);  Write(LogFile,T+': '+Event+#13#10); except end;end; function TLogMaster.RemoveLog: boolean;begin end; end.
|  | Ответ отправил: min@y™ (статус: Доктор наук)Время отправки: 3 августа 2009, 21:42
 Оценка за ответ: 4
 Комментарий к оценке: смысла нет, но есть желание научится) от простого к сложному) |  Ответ #2. Отвечает эксперт: Вадим К Здравствуйте, IlluminatI!Давайте вначале посмотрим, почему данный код плохой. Вы создаете компонент, который наверно захотите поставить на форму. А для этого среда делфи должна уметь вызвать конструктор. Она знает, что все компоненты, которые можно поставить на форму, имеют конструктор с определёнными параметрами. Ваший же конструктор она вызвать не сможет. Она банально не знает, что передать в параметр Filename. Параметры конструктора должны совпадать с параметрами конструктора предка.  Да, в целом, конструктор дочернего класса может отличаться (более того, их может быть много), но тут мы имеем дело с компонентом. Поэтому либо следуем по правилам делфи, либо делаем класс, который не будет компонентом. Можно создать два конструктора, один для делфи, другой для себя, но это отдельная история.
 А что же делать с параметром FileName? либо инициализировать чем то по умолчанию, либо просто не давать работать, пока свойство не будет установлено. А для установки свойства делаем свойство/метод.
 
 замечания к коду
 Write(LogFile,'------ File info -----'+#13#10);
 а рассказывали ли вам о процедуре Writeln? Она сама добавляет перевод строки. То есть надо так
 WriteLn(LogFile,'------ File info -----');
 Хотя в предыдущей строке можно было и плюсик не писать, будет работать:)
 
 AddEvent - открыть файл отрыли, а кто закрывать будет за собой?
 
 overload
 иногда хочеться иметь два-три метода с одинаковыми именами, но разными входными параметрами. Но компилятор ругается, если объявить несколько методов с одинаковым именем. И для того, что бы успокоить компилятор, дать ему понять, что это мы хотим так, и существует ключевое слово overload.
 
 override
 Это ключевое слово нужно, что бы указать компилятору, что мы перекрываем виртуальный метод предка. Мне кажеться, что это синтаксический сахар и можно было бы обойтись без него, но...
 
 то min@y™
 reintroduce;... да, выход конечно. но будет приятное исключение, когда компонент на форму ставить будем:))
 код с IOResult с последующей генерацией исключения... try except чудно умеет их и сам перехватывать.
 
|  | Ответ отправил: Вадим К (статус: Академик)Время отправки: 3 августа 2009, 22:02
 Оценка за ответ: 5
 Комментарий к оценке: Спасибо, буду разбираться) |  Ответ #3. Отвечает эксперт: Amidamaru Здравствуйте, IlluminatI!Думаю стоит начать с override и overload.
 
 overload используется для функций или методов имеющих одно и тоже имя но различные параметры.
 пример использования overload - функция inttostr() которая может принимать в качестве параметра integer и int64.
 
 override используется в при создании нового класса, когда необходимо изменить наследуемый метод.
 при этом описание метода, на котором используется override, должно быть идентично описанию этого метода у "предка".
 
 В этом у вас и ошибка.
 конструктор Create у TComponent имеет вид:
 
 constructor Create(AOwner: TComponent);
 
 точно такоеже описание должно быть и у вас если вы хотите использовать override.
 
 и ещё по мелочам у вас немало ошибок в коде.
 В часности Filename: string лучше вынести как свойство и всё что выполняется в Create перенести в наследуемый метод Loaded;
 
 Заходите какнибудь на IRC канал на dalnet, помогу. А сейчас советую только посмотреть примеры создания несложных компонентов.
 
|  | Ответ отправил: Amidamaru (статус: 4-ый класс)Время отправки: 3 августа 2009, 22:04
 
 |  
 Мини-форум вопросаВсего сообщений: 7; последнее сообщение — 3 августа 2009, 23:01; участников в обсуждении: 3. 
|   | min@y™ (статус: Доктор наук), 3 августа 2009, 21:56 [#1]:Вообще, хреновая идея. Написал бы потомок от TStringList да и всё. Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | Вадим К (статус: Академик), 3 августа 2009, 22:04 [#2]:TStringList в данном случае может будет идеей похуже. Потому что если приложение "резко упадет", то лог не будет сохранен и вся сущность лога коту под хвост. Галочка "подтверждения прочтения" - вселенское зло. |  
|   | Amidamaru (статус: 4-ый класс), 3 августа 2009, 22:09 [#3]:2  min@y™ я думаю в данном случае лучше было бы использовать перегузку Loaded; а не reintroduce. |  
|   | min@y™ (статус: Доктор наук), 3 августа 2009, 22:12 [#4]: Цитата: Потому что если приложение "резко упадет", то лог не будет сохранен и вся сущность лога коту под хвост.
 
 
 Здарова, братская Украина!
 А это как написать...
 Я бы добавил такой метод ---> function TLogFile.Flush(): Boolean;
 Ты ж понимаешь, что должно быть внутри этого метода.
 
 
 Цитата: код с IOResult с последующей генерацией исключения... try except чудно умеет их и сам перехватывать.
 
 
 Да это ж я для примера.
 Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | Вадим К (статус: Академик), 3 августа 2009, 22:27 [#5]:"Да это ж я для примера." Зачем? зачем усложнять жизнь. "function TLogFile.Flush(): Boolean;" ещё раз в лоб. И будешь сбрасывать после каждого добавления строки? или раз на десять? первый лишен смысла - так как тогда StringList не нужен. Второй - тоже, потому что если приложение упало, мы теряем несколько последних сообщений.
 Ещё вопросы?
 Галочка "подтверждения прочтения" - вселенское зло. |  
|   | min@y™ (статус: Доктор наук), 3 августа 2009, 22:58 [#6]: Цитата: Ещё вопросы? У меня их и не было.
 Не надо писать программы, которые резко падают.
 Ну что? неужели опять будем полемику разводить? Я пишу так, как мне удобно, и бесплатно делюсь своим опытом. Причём, не гарантируя, что мои методы правильные. Я расказываю, как я делаю, а не как надо на самом деле.
 Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | Вадим К (статус: Академик), 3 августа 2009, 23:01 [#7]:если бы программы не падали, то и логи не надо... Галочка "подтверждения прочтения" - вселенское зло. |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |