Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.05.2012, 00:29   #1
mongolores
 
Регистрация: 12.05.2012
Сообщений: 9
Вопрос Перегрузка виртуальных методов

Добрый день, уважаемые участники форума. Ищу более опытных людей для решения непосильной пока для меня задачи. Сразу к делу:
Есть абстрактный класс TLogger, описывающий журнал событий (лог). Конечно в нем можно встретить самую наверное основную функцию всех логгеров - запись некоего сообщения в файл или, например, таблицу базы данных. Ну вот что-то вроде:
Код:
TLogger = class
  procedure WriteEntry; virtual; abstract;
end;
На основе этого класса можно создавать реализуемые, не абстрактные классы, которые будут работать с разными форматами лог-сообщений: отдельное сообщение может быть представлено например обычной текстовой строкой, а можно и более развернуто - XML-узлом. Соответственно в процедуру WriteEntry нужно передать сообщение в "родном" для данного класса формате, например:
Код:
 TTXTLogger = class (TLogger)
      procedure WriteEntry(pEnrty: String); override;
  end;

 TXMLLogger = class (TLogger)
      procedure WriteEntry(pEnrty: TXMLNode); override;
  end;
Учитывая, что базовый (абстрактный) класс по-идее понятия не имеет в каком формате будут вестись сообщения, а описывает лишь общие особенности логгера, то и в его проедуру я не могу передать параметр какого-либо конкретного типа:
Код:
TLogger = class
  procedure WriteEntry(pEnrty: ???); virtual; abstract;
end;
А перегрузить виртуальный метод в классе-потомке компилятор тоже не дает:
Код:
// Увы, не прокатило ((
procedure WriteEntry(pEnrty: String); override; overload;
procedure WriteEntry(pEnrty: TXMLNode); override; overload;
Я - максималист )) Люблю, когда задача реализована ясно и профессионально. Помогите, пожалуйста, сохранить абстрактный класс (ведь он описывает основные свойства для потомков!) и научить методы потомков работать с данными, которые неизвестны предку.
Заранее спасибо за участие!
mongolores вне форума Ответить с цитированием
Старый 13.05.2012, 00:39   #2
SNUPY
Форумчанин
 
Регистрация: 15.02.2008
Сообщений: 621
По умолчанию

однако порно ^_^
Код:
  TLogger = class
    public
      procedure WriteEntry; dynamic; abstract;
  end;


  TTXTLogger = class (TLogger)
    private
      procedure WriteEntry; overload; override;
    public
      procedure WriteEntry(pEnrty: String); overload;
  end;
Помог? Ну так нажми на весы!
SNUPY вне форума Ответить с цитированием
Старый 13.05.2012, 00:40   #3
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

override из наследника нужно убрать
предупреждение типа "метод WriteEntry скрыл виртуальный метод базового типа" останется
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 13.05.2012, 00:51   #4
SNUPY
Форумчанин
 
Регистрация: 15.02.2008
Сообщений: 621
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
override из наследника нужно убрать
предупреждение типа "метод WriteEntry скрыл виртуальный метод базового типа" останется
Извините пожалуйста меня уважаемый! Но по моему абстрактные методы не спроста делаются ведь. Сколько я понимаю создание абстрактного метода вызвано тем, что в родительском классе есть участки кода, где можно уже выразился явный алгоритм, но вот ведь мать его, одного или нескольких методов сейчас вот никак не определишь для реализации данного алгоритма. И поэтому вот такое решение
Цитата:
override из наследника нужно убрать
может сыграть в злую шутку потом.
Либо я вас не правильно понял. А вообще лучше покажите что вы имели введу.
Помог? Ну так нажми на весы!
SNUPY вне форума Ответить с цитированием
Старый 13.05.2012, 01:03   #5
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Согласен, переклинило насчет абстрактного
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 13.05.2012, 10:26   #6
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,899
По умолчанию

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

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

Я бы предложил довольно избитый способ - способ борланда, передавать (всеми любимый, гы) Sender: TObject, ну, или точнее в данном случае pEntry: Object , если конечно подхакерить (ну точнее баловаться контрактом), то можно кидать и строки туда в виде WriteEntry(TObject(MyStr)), но если сильно уперлись строки , то можно вместо TОbject сразу Pointer объявить, а там уж каждый наследник кастует к нужному ему типу.
Только есть небольшой геморрой в этом, я бы уберегся создав собственную иерархию оберток под объекты, т.е. создать базовый Tentry, в него нужные поля, потом куча наследников этого энтри со своими полями, ну а логгер абстрактный принимает этjго Tentry, а каждый потомок логгера кастует эту ентрю к своему типу.

Последний раз редактировалось phomm; 13.05.2012 в 10:30.
phomm вне форума Ответить с цитированием
Старый 13.05.2012, 20:48   #7
SNUPY
Форумчанин
 
Регистрация: 15.02.2008
Сообщений: 621
По умолчанию

Немного допешу что я имел введу =)
Код:
  TLogger = class
    public
      procedure WriteEntry; dynamic; abstract;
  end;


  TTXTLogger = class (TLogger)
    private
      FpEnrty: string
      procedure WriteEntry; overload; override;
    public
      procedure WriteEntry(pEnrty: String); overload;
  end;
...
procedure TLogger.WriteEntry;
begin
   ...
   WriteEntry(FpEnrty);
   ...
end;
Помог? Ну так нажми на весы!
SNUPY вне форума Ответить с цитированием
Старый 13.05.2012, 21:14   #8
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Из вопроса не ясно, а зачем, собственно, нужен виртуальный абстрактный метод у класса-предка. Ведь вызвать его нельзя.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 13.05.2012, 21:51   #9
3D Hunter
Сумрачная тень
Форумчанин
 
Аватар для 3D Hunter
 
Регистрация: 05.03.2009
Сообщений: 689
По умолчанию

Ну, абстрактный метод не может быть не виртуальным. Обычно такие абстрактные классы являются шаблонами-заготовками для полноценных рабочих классов. Например, как класс TStrings.
Как вариант, действительно, в методе предка тип параметра лучше сделать вообще Pointer или Variant:
Код:
  procedure WriteEntry(const AVal:Pointer); virtual; abstract;
//или
  procedure WriteEntry(const AVal:Variant); virtual; abstract;
end;
"ковыряю изнутри" (с)
3D Hunter вне форума Ответить с цитированием
Старый 14.05.2012, 01:18   #10
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Я не это имел в виду.

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

В задаче же, как она указана в вопросе, метод вообще нельзя вызвать, не зная деталей реализации. Иными словами, если у нас есть ссылка на TLogger, мы не можем вызвать WriteEntry, не зная о том, какой именно это подкласс (чтобы передать ему нужный параметр).

Внимание, вопрос: а нафига этот метод тогда нужен?
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Перегрузка виртуальных функций при полиморфизме Стремящийся Общие вопросы C/C++ 2 06.05.2012 10:23
снова об виртуальных машинах. Пепел Феникса Общие вопросы по программированию, компьютерный форум 12 25.08.2011 23:35
перегрузка виртуальных функций tiger() Visual C++ 2 04.05.2011 07:35
Конфликт виртуальных серверов ZvEr_HaCkEr Свободное общение 4 19.04.2011 18:37
Построение виртуальных миров qqwer1984 Gamedev - cоздание игр: Unity, OpenGL, DirectX 28 19.07.2010 21:22