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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 19.11.2012, 16:14   #1
Sasha_S
Пользователь
 
Регистрация: 28.04.2011
Сообщений: 16
По умолчанию Нужен ликбез по интерфейсам на примере IXMLNode

Всем привет!
Осваиваю ООП. У меня совсем нет опыта работы с интерфейсами в Delphi, но очень хочется сделать правильно и объектно-ориентированно. Прошу помощи.

Нужно прочитать данные о цепочке отрезков из XML-файла. Пример файла:

Код:
<Chain>
  <Node x="0" y="0">
  <Node x="100" y="0">
  <Node x="100" y="100">
</Chain>
В XML-файле данные хранятся по точкам; мне нужно перевести точки в отрезки, то есть при создании каждого отрезка считывать не по одному элементу XML, а по два сразу: текущий и следующий, начальную точку и конечную.

Я делаю так:

Код:
type

TForm1 = class(TForm)
  ...
  function GetNextXMLNode(Node: IXMLNode): IXMLNode;
  //То есть "получить для узла Node следующий узел в цепочке"
end;

TLine = class
  XStart, YStart, XEnd, YEnd: integer;
  procedure LoadFromXML(Node: IXMLNode);
end;

...

procedure TLine.LoadFromXML(Node: IXMLNode);
var
  NextNode: IXMLNode;
begin
  XStart := StrToInt(Node.Attributes['x']);
  YStart := StrToInt(Node.Attributes['y']);

  //Далее идет вызов той самой функции:
  NextNode := Form1.GetNextXMLNode(Node);

  XEnd := StrToInt(NextNode.Attributes['x']);
  YEnd := StrToInt(NextNode.Attributes['y']);
end;
Проблема: я хочу перенести функцию GetNextXMLNode из класса TForm1, потому что ну не место ей там! Хочется сделать что-то вроде класса-потомка IXMLNode, для которого можно будет написать так:

Код:
procedure TLine.LoadFromXML(Node: IXMLLineNode);
var
  NextNode: IXMLNode;
begin
  ...
  NextNode := Node.GetNextXMLNode;
  ...
end;
Что для этого нужно сделать? Как объявить этот класс-потомок? Я пробовала сделать так:

Код:
  IXMLLineNode = interface(IXMLNode)
  ['{AD299527-3D7B-43E6-9C66-30356930F137}']
    function GetNextPrimitiveNode: IXMLNode;
  end;

  TXMLLineNode = class(IXMLLineNode)
    function GetNextPrimitiveNode: IXMLNode;
  end;
- на что Delphi пишет: Class type required. Теоретически я понимаю, с чем это связано: один интерфейс объявить мало, нужен еще и класс, но какой класс следует указать и как это правильно сделать? Подскажите, пожалуйста.
Sasha_S вне форума Ответить с цитированием
Старый 23.11.2012, 10:43   #2
Sasha_S
Пользователь
 
Регистрация: 28.04.2011
Сообщений: 16
По умолчанию

Вот чем все закончилось.

Я изначально была неправа, когда писала TXMLLineNode = class(IXMLLineNode). При такой записи мне пришлось бы самостоятельно с нуля расписывать реализацию всех функций интерфейса IXMLNode - интерфейс сообщает только о заголовках функций и процедур, которые должен содержать класс, на то он и интерфейс. Переломной в ходе ликбеза для меня стала вот эта статья - коротко, по теме и с примерами.

Это означает, что если и наследовать, то не от интерфейса IXMLNode, а от класса, который реализует этот интерфейс и который в Delphi применяется при обработке узлов XML. Это класс TXMLNode модуля XMLDoc, и теперь все становится просто: создавать наследник TXMLLineNode = class(TXMLNode). Но:

в справке по RAD Studio говорится:

Цитата:
The XML Data Binding Wizard uses TXMLNode as a base class for the classes it generates to represent nodes that have child nodes... Each TXMLNode descendant implements a class-specific interface that descends from IXMLNode. Typically, applications do not work directly with TXMLNode. Instead, they use the IXMLNode interface or the IXMLNode descendant that is implemented by a TXMLNode descendant.
Я поняла это так (поправьте, если неправильно): при обработке XML-файла автоматически генерируются некоторые классы-потомки TXMLNode, специфические для каждого узла, и не видя файла, мы не можем предугадать, что это будет за класс-потомок. Потому и обращение к ним производится через интерфейс: единственное, что мы точно знаем о характеристиках класса-потомка, это то, что он реализует указанные методы и свойства. Так что вклиниваться со своим TXMLLineNode мне пришлось бы в самый процесс считывания элементов файла, что неоправданно сложно.

Поэтому от функции GetNextNode я отказалась вообще и просто добавила этот код в свою процедуру LoadFromXML - не так уж и много в ней было строк. Куда еще можно было перенести мою функцию из TForm1 - другой вопрос. Но эта тема вроде бы закрыта. Спасибо, кто читал.
Sasha_S вне форума Ответить с цитированием
Старый 23.11.2012, 11:55   #3
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,899
По умолчанию

Хм, не видел этой темы тут.
А что мешало использовать ChildNodes ?
Я бы читал каждый чейн и передавал в загрузчик, а загрузчик по порядку грузил бы каждую точку связывая как ему надо (я так понимаю, примерно так и сделали, возможно даже используя чайлдов)
А вынести функцию в любое место, но имхо рационально сделать некий загрузчик и у него будет список вершин (или список чейнов со списками вершин) к коим он будет давать доступ извне (из формы или точнее из вьюхи, см. MVC ), и его вьюха будет просить загрузить нужный файл, и он его почейново грузит.

Вообще , как я понимаю, некоторая проблема стоит в проектировании, ведь одна нода на уровне не должна ничего знать о других нодах, ибо они лишь элементы во владельце-контейнере и он заправляет возможности обращения к поднодам. Поэтому лучше было бы иметь ноды с 4 координатами (пусть и с избыточной инфой). А если надо с двумя, попарно объединяя ноды и подразумевая , что они именно подряд (хотя емнип, это не гарантировано в хмл) то тут надо и бизнес-логику иметь соответствующую. Ведь сами подумайте, если неделимая сущность в вашей системе это линия (Вы же создали класс ТЛайн) и Вы ею заправляете , то зачем искусственно её делить ?
Программируйте на языке предметной области.
phomm вне форума Ответить с цитированием
Старый 23.11.2012, 16:00   #4
Sasha_S
Пользователь
 
Регистрация: 28.04.2011
Сообщений: 16
По умолчанию

phomm, большое спасибо за ссылку на MVC! Это как раз то, на чем у меня пока пробел. Буду читать.

Проблема со структурой файла есть, но я получаю его уже в готовом виде из другой программы. Хотя да, есть обратная связь с разработчиком и возможность изменить формат. Мое решение представлять данные по линиям обосновано и алгоритмом, и форматами файлов, и связкой с другой системой.
Цитата:
Сообщение от phomm Посмотреть сообщение
Я бы читал каждый чейн и передавал в загрузчик, а загрузчик по порядку грузил бы каждую точку связывая как ему надо (я так понимаю, примерно так и сделали, возможно даже используя чайлдов)
Да, так и делаю. Напрямую к ChildNodes[i] и [i+1] не обращаюсь, потому что структура может быть сложнее, и кроме <Node/> могут попадаться потомки другого типа (а именно вложенные цепочки <Chain></Chain> - внутренние границы для областей с отверстиями). А могут и не попадаться. Поэтому там именно функция поиска следующего элемента типа Node.
Sasha_S вне форума Ответить с цитированием
Старый 23.11.2012, 19:49   #5
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,899
По умолчанию

Один из самых мною уважаемых мануалов по дельфи, раздел про интерфейсы: http://delphikingdom.ru/asp/viewitem.asp?catalogid=1202
это для ликбеза по интерфейсам
phomm вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
SSE инструкции + ликбез Kukurudza Общие вопросы C/C++ 4 10.04.2012 19:26
Ошибка в примере K&R 8Observer8 Общие вопросы C/C++ 20 22.12.2011 12:33
Ubuntu Linux: настроил Ин-т(PPPoE). Нужен краткий ликбез опытного линуксоида по поводу безопасности Alexei91 Безопасность, Шифрование 7 24.06.2011 06:32
cisco packet tracer ликбез the_deer_one Свободное общение 0 14.06.2011 13:04