Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 3 062

/ вопрос открыт /

Приветствую, уважаемые эксперты!
У меня такая проблема: я первый раз пытаюсь написать компонент (а вместе с ним и новый класс с конструктором), почитал несколько статей по созданию компонентов, так же почитал про классы. Решил для начала создать легкий компонент, который управляет лог-файлом. Вот основные проблемы:

1) При компиляции выдается ошибка:

[Error] LogMaster.pas(21): Declaration of 'Create' differs from previous declaration (код в приложении), в чем тут дело?

2) немогли бы вы по подробней рассказать когда следует использовать override, overload?

Приложение:
  1. unit LogMaster;
  2.  
  3. interface
  4.  
  5. uses
  6. SysUtils, Classes, Forms;
  7.  
  8. type
  9. TLogMaster = class(TComponent)
  10. procedure AddEvent(Event: string);
  11. function RemoveLog: boolean;
  12. private
  13. LogFile: text;
  14. T: string;
  15. { Private declarations }
  16. protected
  17. { Protected declarations }
  18. public
  19. { Public declarations }
  20. published
  21. constructor Create(FileName: string); override;
  22. { Published declarations }
  23. end;
  24.  
  25. procedure Register;
  26.  
  27. implementation
  28.  
  29. procedure Register;
  30. begin
  31. RegisterComponents('Log Master', [TLogMaster]);
  32. end;
  33.  
  34. constructor TLogMaster.Create(FileName: string);
  35. var D: string;
  36. begin
  37. D:=DateToStr(Now);
  38. T:=TimeToStr(Now);
  39. FileName:=FileName+'_log.txt';
  40. AssignFile(LogFile, FileName);
  41. try
  42. Rewrite(LogFile);
  43. Write(LogFile,'------ File info -----'+#13#10);
  44. Write(LogFile,'## Log File From "'+ExtractFileName(Application.ExeName)+'"'+#13#10);
  45. Write(LogFile,'## Start Date: '+D+#13#10);
  46. Write(LogFile,'## Start Time: '+T+#13#10);
  47.  
  48. Write(LogFile,'------ Start Log -----'+#13#10+#13#10+#13#10);
  49. CloseFile(LogFile);
  50. except
  51. end;
  52. end;
  53.  
  54. procedure TLogMaster.AddEvent(Event: string);
  55. begin
  56. try
  57. Append(LogFile);
  58. Write(LogFile,T+': '+Event+#13#10);
  59. except
  60. end;
  61. end;
  62.  
  63. function TLogMaster.RemoveLog: boolean;
  64. begin
  65. end;
  66.  
  67. end.


IlluminatI Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: IlluminatI (статус: 2-ой класс)
Вопрос отправлен: 3 августа 2009, 21:19
Состояние вопроса: открыт, ответов: 3.

Ответ #1. Отвечает эксперт: min@y™

Как говорится, найди 10 отличий и тогда всё поймёшь.

Какой смысл делать такой класс компонентом?

Приложение:
  1. unit LogMaster;
  2.  
  3. interface
  4.  
  5. uses
  6. SysUtils, Classes, Forms;
  7.  
  8. type
  9. TLogMaster = class(TComponent)
  10. procedure AddEvent(Event: string);
  11. function RemoveLog: boolean;
  12. private
  13. LogFile: text;
  14. T: string;
  15.  
  16. protected
  17. { Protected declarations }
  18. public
  19. { Public declarations }
  20. published
  21. constructor Create(AOwner: TComponent; const FileName: string); reintroduce;
  22.  
  23. end;
  24.  
  25. procedure Register;
  26.  
  27. implementation
  28.  
  29. procedure Register;
  30. begin
  31. RegisterComponents('Log Master', [TLogMaster]);
  32. end;
  33.  
  34. constructor TLogMaster.Create(AOwner: TComponent; const FileName: string);
  35. var D: string;
  36. begin
  37. inherited Create(AOwner);
  38.  
  39. D:=DateToStr(Now);
  40. T:=TimeToStr(Now);
  41.  
  42.  
  43.  
  44.  
  45. AssignFile(LogFile, FFileName);
  46. {$I-}
  47. Rewrite(LogFile);
  48. Write(LogFile,'------ File info -----' + #13#10);
  49. Write(LogFile,'## Log File From "' + ExtractFileName(Application.ExeName)+'"'+#13#10);
  50. Write(LogFile,'## Start Date: ' + D + #13#10);
  51. Write(LogFile,'## Start Time: ' + T + #13#10);
  52.  
  53. Write(LogFile,'------ Start Log -----'+#13#10+#13#10+#13#10);
  54. CloseFile(LogFile);
  55. {$I+}
  56. if IOError <> 0
  57. then raise;
  58. end;
  59.  
  60. procedure TLogMaster.AddEvent(Event: string);
  61. begin
  62. try
  63. Append(LogFile);
  64. Write(LogFile,T+': '+Event+#13#10);
  65. except
  66. end;
  67. end;
  68.  
  69. function TLogMaster.RemoveLog: boolean;
  70. begin
  71.  
  72. end;
  73.  
  74. 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™

min@y™ (статус: Доктор наук), 3 августа 2009, 21:56 [#1]:

Вообще, хреновая идея. Написал бы потомок от TStringList да и всё.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
Вадим К

Вадим К (статус: Академик), 3 августа 2009, 22:04 [#2]:

TStringList в данном случае может будет идеей похуже. Потому что если приложение "резко упадет", то лог не будет сохранен и вся сущность лога коту под хвост.
Галочка "подтверждения прочтения" - вселенское зло.
Amidamaru

Amidamaru (статус: 4-ый класс), 3 августа 2009, 22:09 [#3]:

2 min@y™ я думаю в данном случае лучше было бы использовать перегузку Loaded; а не reintroduce.
Приглашаю Вас на наш IRC-канал: #delphiintru в сети DalNet.
min@y™

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™

min@y™ (статус: Доктор наук), 3 августа 2009, 22:58 [#6]:

Цитата:

Ещё вопросы?

У меня их и не было.
Не надо писать программы, которые резко падают.
Ну что? неужели опять будем полемику разводить? Я пишу так, как мне удобно, и бесплатно делюсь своим опытом. Причём, не гарантируя, что мои методы правильные. Я расказываю, как я делаю, а не как надо на самом деле.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
Вадим К

Вадим К (статус: Академик), 3 августа 2009, 23:01 [#7]:

если бы программы не падали, то и логи не надо...
Галочка "подтверждения прочтения" - вселенское зло.

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:41
Выполнено за 0.03 сек.