2013-08-15 3 views
4

мне нужно разработать следующий класс диаграммы: enter image description here
Я написал код, но есть проблемы с единичной ссылкой круговой.Циклическая ссылка между классом

XmlFileManager Класс содержит:

unit XmlFileManager; 
interface 
uses 
    xmldom, XMLIntf, msxmldom, XMLDoc, SysUtils, DateUtils, Classes, Dialogs, 
    XmlEnpManager; 
type 
    TXmlFileManager = class 
    private 
    [...] 
    xmEnp: TXmlEnpManager; 
    xmEnpInicial: TXmlEnpManager; 
    xmEnpFinal: TXmlEnpManager; 
[...] 
end. 

Абстрактный класс, XmlNodeManager:

unit XmlNodeManager; 
interface 
uses 
    xmldom, XMLIntf, msxmldom, XMLDoc, SysUtils, DateUtils, Classes, Dialogs, 
    XmlFileManager; 
type 
    TXmlNodeManager = class 
    protected 
     { sgy alias para strategy } 
     sgyIterator: Integer; 
     sgyContext: TXmlFileManager; 
     sgyAttributes: TStringList; 
     sgyNode: IXMLNode; 
[...] 
end. 

И конкретный класс XmlEnpManager:

unit XmlEnpManager; 
interface 
uses 
    xmldom, XMLIntf, msxmldom, XMLDoc, SysUtils, DateUtils, Classes, Dialogs, 
    XmlNodeManager; 
type 
    TXmlEnpManager = class (TXmlNodeManager) 
    public 
     constructor Create(aContext: TXmlFileManager); overload; override; 
     constructor CreateInicial(aContext: TXmlFileManager); reintroduce; overload; 
     constructor CreateFinal(aContext: TXmlFileManager); reintroduce; overload; 
[...] 
end. 

сборки с ошибкой:

[dcc32 Fatal Error] XmlNodeManager.pas(7): F2047 Circular unit reference to 'XmlFileManager'

Любые идеи, как решить эту проблему?.

+9

Это правая королевская боль в прикладе. Программисты, знакомые с другими языками, задаются вопросом, о чем мы говорим. Почему это даже проблема? Циркулярные ссылки приводят вас неумолимо к тому, чтобы весь ваш код был в одном устройстве. Вы когда-нибудь задумывались, почему исходные файлы Delphi имеют тенденцию быть настолько большими? Посмотрите на некоторые из блоков VCL. Полные монстры. В немалой степени именно поэтому исполняемые файлы Delphi настолько огромны по размеру.Последние изменения RTTI сделали это еще хуже. Конечно, вы можете использовать интерфейсы для разрыва зависимостей. Но это классическая собака с хвостом. Он дует. –

ответ

0

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

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

+0

, если использовать «в реализации» тип переменных экземпляра, не работает. – ramiromd

+0

Нет, это не так, из-за зависимостей в отправленном коде. Два из классов должны быть в одной и той же единице. –

+0

Или они должны быть потомками класса в третьем подразделении. – mg30rg

1

Если возможно, проще всего иметь все классы в одном устройстве.

+1

Все классы этого же подразделения? вау другой путь? – ramiromd

+0

Да, добро пожаловать в больничный шкафчик –

+0

Это возможность. Зависит от ваших стандартов кодирования, если вы хотите его использовать :) – Harriv

0

В XMLNodeManager, Сделано:

sgyContext: TObject;

Тогда вам не нужно использовать устройство XmlFileManager в интерфейсе. Используйте его в разделе «Использование» раздела «Реализация». При использовании sgyContext в коде реализации передайте его в TXmlFileManager (sgyContext).

+3

Это ужасная идея. Это означает, что вы должны иметь уродливые приемы типов повсюду, и компилятор не может поймать никаких ошибок (вы можете ошибочно передать «TButton», и он позволит это и попытаться направить кнопку в качестве «TXMLFileManager» - он будет компилироваться и запускаться, но почти наверняка взорвется во время выполнения). –

+0

sgyContext - это не то, что часто передается через параметр. Это член, и член может быть установлен в конструкторе или в служебной функции, где может быть код, который проверяет тип класса перед его настройкой. После правильной установки нет ошибок. Иногда, когда у вас должны быть единицы, которые должны быть разделены, такая техника может работать. Я понимаю, что с точки зрения «пуриста» это нет, нет. Но мы смотрим на все возможные решения, и это решение. –

+0

Нет. :-) Вы прилагаете все усилия, чтобы реализовать плохую идею, чем прежде всего, чтобы сделать это правильно. Кроме того, чтобы придать этому типу все это место, вы добавили код, чтобы предотвратить случайное прохождение неправильного типа * во время выполнения *, при правильном выполнении он позволял компилятору * сначала проверять его * и предотвращать ошибку в первом место. Плохой код, который теперь складывается поверх плохого кода, не делает лучшего кода. Это не решение - это вонючий код, сложенный поверх вонючего кода, для реализации плохого решения. –

5

Помещенный TXmlFileManager и TXmlNodeManager как в том же unit и ту же type секции, то убедитесь, что type раздел начинается с этим классом вперед: TXmlNodeManager = class;

Смотрите официальную документацию: Forward Declarations and Mutually Dependent Classes.

unit XmlFileManagerAndXmlNodeManager; 
interface 
uses 
    xmldom, XMLIntf, msxmldom, XMLDoc, SysUtils, DateUtils, Classes, Dialogs, 
[...] 

type 
    TXmlNodeManager = class; 

    TXmlFileManager = class 
    private 
    [...] 
    xmEnp: TXmlEnpManager; 
    xmEnpInicial: TXmlEnpManager; 
    xmEnpFinal: TXmlEnpManager; 
[...] 

    TXmlNodeManager = class 
    protected 
     sgyIterator: Integer; 
     sgyContext: TXmlFileManager; 
     sgyAttributes: TStringList; 
     sgyNode: IXMLNode; 
[...] 
end. 
1

Хотя положить все классы в одном блоке является идеальным решением, вы могли бы рассмотреть нарушения взаимной ссылки путем взаимодействия по меньшей мере, один из классов, определяя, что интерфейс в виде отдельного блока и позволяя другой блок см блок с интерфейсом в разделе интерфейса. Затем вы можете перенести первую ссылку на единицу с интерфейса на реализацию. Затем будет создан экземпляр в разделе реализации, где допускается взаимная ссылка, но тем самым нарушается взаимная ссылка в секции интерфейса, которая не является разрешено, как вы уже заметили. Это позволяет вам сохранить оба класса в отдельном блоке, если это потребуется. Надеюсь, это имеет смысл.

Смежные вопросы