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

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

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

Delphi.int.ru Expert

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

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

#   

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


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

Подробнее »



Вопрос # 3 149

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

Доброго времени суток, уважаемые эксперты!
Я учусь писать классы, и возникли такие проблемы:

1) Написал класс, по задаче (в приложении), возникает ошибка Stack overflow. Не могли бы вы объяснить, почему?
2) Расскажите пожалуйста, как грамотно работать со свойствами классов (property)?
3) Можете по-подробней рассказать про виртуальные и абстрактные классы а так же зачем используется reintroduce? Покапался в интернете, ничего полезно не нашел =\

P.S: решение задачи мне не нужно, с этим я справлюсь и записями. Просто хотелось бы на примере этой задачи получше разобраться с классами. Заранее спасибо!

К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса)

Приложение:
  1.  
  2.  
  3.  
  4. program Project1;
  5.  
  6. {$APPTYPE CONSOLE}
  7.  
  8. uses
  9. SysUtils;
  10.  
  11. type TBenzinMark = 90..100;
  12. type TPriceType = 1000..3000;
  13.  
  14. type
  15. TAZS = class
  16. FCompany, FStreet: string;
  17. FMark: TBenzinMark;
  18. FPrice: TPriceType;
  19. function GetMark: TBenzinMark;
  20. procedure SetMark(aMark: TBenzinMark);
  21. function GetCompany: string;
  22. procedure SetCompany(aCompany: string);
  23. function GetStreet: string;
  24. procedure SetStreet(aStreet: string);
  25. function GetPrice: TPriceType;
  26. procedure SetPrice(aPrice: TPriceType);
  27. //
  28. property Company: string read GetCompany write SetCompany;
  29. property Street: string read GetStreet write SetStreet;
  30. property Mark: TBenzinMark read GetMark write SetMark;
  31. property Price: TPriceType read GetPrice write SetPrice;
  32. end;
  33.  
  34. { TAZS }
  35.  
  36. function TAZS.GetCompany: string;
  37. begin
  38. Result:=FCompany;
  39. end;
  40.  
  41. function TAZS.GetMark: TBenzinMark;
  42. begin
  43. Result:=FMark;
  44. end;
  45.  
  46. function TAZS.GetPrice: TPriceType;
  47. begin
  48. Result:=FPrice;
  49. end;
  50.  
  51. function TAZS.GetStreet: string;
  52. begin
  53. Result:=FStreet;
  54. end;
  55.  
  56. procedure TAZS.SetCompany(aCompany: string);
  57. begin
  58. FCompany:=aCompany;
  59. end;
  60.  
  61. procedure TAZS.SetMark(aMark: TBenzinMark);
  62. begin
  63. FMark:=aMark;
  64. end;
  65.  
  66. procedure TAZS.SetPrice(aPrice: TPriceType);
  67. begin
  68. FPrice:=aPrice;
  69. end;
  70.  
  71. procedure TAZS.SetStreet(aStreet: string);
  72. begin
  73. FStreet:=aStreet;
  74. end;
  75.  
  76. var A: TAZS;
  77.  
  78. begin
  79. try
  80. a.SetMark(95);
  81. a.SetCompany('Nubovoz');
  82. a.SetStreet('Lolobasovo 8');
  83. a.SetPrice(2500);
  84. { TODO -oUser -cConsole Main : Insert code here }
  85. writeln(a.GetMark);
  86. readln;
  87. except
  88. on E:Exception do
  89. Writeln(E.Classname, ': ', E.Message);
  90. end;
  91. end.
  92.  


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

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

Ответ #1. Отвечает эксперт: Вадим К

Здравствуйте, IlluminatI!
Не знаю, каким образом возникла эта ошибка (она может возникать, я знаю когда, но в данном случае нет причин). Но есть другая проблема - конструктор класса надо вызвать. И свойства дергать правильно. То есть код как минимум должен выглядеть так

try
   a := TAZS.Create;
   a.Mark := 95;
   a.Company := 'Nubovoz';
   a.Street := 'Lolobasovo 8';
   a.Price := 2500;
    { TODO -oUser -cConsole Main : Insert code here }
    writeln(a.Mark);
    readln;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
Само объявление тоже надо писать красиво, а то все свойства стали приватными:)
объявление класса должно выглядеть где то так
type
 TAZS = class
  private
    FCompany, FStreet: string;
    FMark: TBenzinMark;
    FPrice: TPriceType;
    function GetMark: TBenzinMark;
    procedure SetMark(aMark: TBenzinMark);
    function GetCompany: string;
    procedure SetCompany(aCompany: string);
    function GetStreet: string;
    procedure SetStreet(aStreet: string);
    function GetPrice: TPriceType;
    procedure SetPrice(aPrice: TPriceType);
    //
  public
    property Company: string read GetCompany write SetCompany;
    property Street:  string read GetStreet write SetStreet;
    property Mark: TBenzinMark read GetMark write SetMark;
    property Price: TPriceType read GetPrice write SetPrice;
 end;

Цитата:


Можете по-подробней рассказать про виртуальные и абстрактные классы

Это долгий разговор, устану писать. Может учебник достать?

Цитата:

а так же зачем используется reintroduce

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

Цитата:

Расскажите пожалуйста, как грамотно работать со свойствами классов (property)?

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

Ответ отправил: Вадим К (статус: Академик)
Время отправки: 3 сентября 2009, 19:22
Оценка за ответ: 5

Комментарий к оценке: спасибо за разъяснения, но есть еще вопросы :)

Мини-форум вопроса

Всего сообщений: 11; последнее сообщение — 4 сентября 2009, 11:05; участников в обсуждении: 4.
IlluminatI

IlluminatI (статус: 2-ой класс), 3 сентября 2009, 19:34 [#1]:

Извините за названия - это я от фонаря писал, для проверки :). Stack overflow обычно при рекурсиях возникает, когда стэк переполняется? Может, посоветуете какой нибудь толковый учебник по классам? А то у меня "В.В. Фаронов - Delphi. Программирование на языке высокого уровня", а там про классы всего 4-5 страниц, и ни одного упоминяния про виртуальные и абстрактные.
А насчет свйоств, я не совсем понимаю принцип их работы. Требуется вводить переменную и свойство, чтобы оформить свойство. Не проще ли обрящятся напрямую к переменной? например a.Company = 'lala'; чем писать два метода для нее? или я что-то недопонимаю %)
Паровоз

Паровоз (статус: 10-ый класс), 3 сентября 2009, 19:45 [#2]:

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

IlluminatI (статус: 2-ой класс), 3 сентября 2009, 19:53 [#3]:

Логично, но при кодинге, в списке (Code Helper или Code Complection вроде называется, точно не помню) появляется и переменная и метод. Это немного смущает, так как при работе со сторонними классами, я этого не замечал. Их как то можно скрыть или все таки я не внимательный? :)
Паровоз

Паровоз (статус: 10-ый класс), 3 сентября 2009, 20:52 [#4]:

Рассмотрим пример. В интерфейсной части модуля unit1 пишем
  TMy = class
  private
    Fx:Integer;
  public
    property x:Integer read Fx write Fx;
  end;
В модуле unit2 используем unit1 и переменную ob типа TMy. Если Вы теперь напишите ob и поставите после него точку, то Code Complection не покажет поля Fx.
IlluminatI

IlluminatI (статус: 2-ой класс), 3 сентября 2009, 21:00 [#5]:

Аа, теперь проясняется :) Спасибо, буду разбираться :)
min@y™

min@y™ (статус: Доктор наук), 3 сентября 2009, 21:15 [#6]:

Могу тебе скинуть один свой интересный модуль. В этом модуле реализованы настройки некой моей программы (не важно, какой). Все настройки реализованы классами и сохраняются в XML (но это не важно).
Ты этот модуль почитаешь (будешь читать-то?) и сразу поймёшь такие вещи, как полиморфизЬм и инкапсуляцЫя.
В модуле полно комментариев. Скинуть тебе?
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
IlluminatI

IlluminatI (статус: 2-ой класс), 3 сентября 2009, 21:36 [#7]:

давай, буду очень благодарен
min@y™

min@y™ (статус: Доктор наук), 3 сентября 2009, 21:46 [#8]:

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

Паровоз (статус: 10-ый класс), 3 сентября 2009, 22:15 [#9]:

"абсолютно правильный ответ мне дала женщина лет 45-и"
Посмотрел авторские данные min@y™:

Q: Авторизуй меня в аське.
A (для мущин): пожалуйста!
А (для женщин): только после секса!
min@y™

min@y™ (статус: Доктор наук), 3 сентября 2009, 22:37 [#10]:

Цитата (Паровоз):


Посмотрел авторские данные min@y™:

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

Вадим К (статус: Академик), 4 сентября 2009, 11:05 [#11]:

Зачем заворачивают переменную в свойство с двумя методами? да все примитивно просто. Вот представим себе кнопку и свойство "надпись на ней". понятно, что если пользователь сменил его, то надо перерисовать кнопку. И если это была бы просто переменная, то отследить это изменение было бы очень сложно (конечно компилятор может отслеживать все это...). А если есть метод, то всё просто - метод может проверить новое значение, перерисовать, отослать администратору сообщение..., мало чего.
Галочка "подтверждения прочтения" - вселенское зло.

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

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