Страница 1 из 5

Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 12:29:13
Brainenjii
Как реализовать? Когда у первого класса свойством должна быть коллекция объектов второго класса, а у второго - свойство с коллекцией объектов первого класса?

Re: Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 12:36:38
stikriz
А в чем проблема?

T2Class = class;

T1Class = class
property Item[Index: Integer]: T2Class ...
...

T2Class = class
property Item[Index: Integer]: T1Class ...
...

Re: Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 12:37:24
Brainenjii
Ах, да.... ОЧЕНЬ (вот просто люто-бешено) хочется чтобы всё было в разных модулях :-(

Добавлено спустя 19 секунд:
Когда уже в FPC будет поддержка пространств имён :-(

Re: Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 13:00:25
alexs
А кто мешает разнести по разным модулям?
Странная здача - из разряда сферических коней в вакуме...

Re: Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 13:30:24
Brainenjii
Модуль длиннее 700 строк (эмпирическое наблюдение) меня начинает напрягать. Поэтому объединения нескольких классов в один модуль, за редким исключением, стараюсь избежать.
Код: Выделить всё

Unit UnitA;

{$mode objfpc}{$H+}

Interface

Uses
  Classes, SysUtils;

Type

{ ClassB }

ClassA = Class
  Public
    // тут должен быть класс B
End;

Implementation

End.

Код: Выделить всё

Unit UnitB;

{$mode objfpc}{$H+}

Interface

Uses
  Classes, SysUtils;

Type

{ ClassB }

ClassB = Class
  Public
    // тут должен быть класс A
End;

Implementation

End.

Как я это разнесу по разным модулям? Я знаю только костыльное полурешение с инклюдами...

Re: Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 14:06:38
zub
Такое в паскале наврятли появится, это скорее ошибка проектирования программы, чем недостаток языка.
Я обычно выкручиваюсь так
Код: Выделить всё
Unit UnitA;

{$mode objfpc}{$H+}

Interface

Uses
  Classes, SysUtils;

Type

{ ClassB }

ClassA = Class
  Public
    // тут абстрактный предок класса B с нужным функционалом
End;

Implementation

End.

Код: Выделить всё
Unit UnitB;

{$mode objfpc}{$H+}

Interface

Uses
  Classes, SysUtils;

Type

{ ClassB }

ClassB = Class
  Public
    // тут абстрактный предок класса А с нужным функционалом
End;

Implementation

End.

Правда классы плодятся как грибы, тоже не гут((

Re: Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 14:24:05
Brainenjii
хм... спасибо ^_^
это скорее ошибка проектирования программы

Вот часто слышу такое. Но не могу понять, что ошибочного в этой идее.
Есть класс, он должен иметь список учеников. Есть ученик, которому было бы очень неплохо знать, в каком классе он учится.
Почему для такой банальной ситуации приходится изворачиваться, заносить оба (дальше - больше) класса в один исходный файл или создавать абстрактный класс... Ну неудобно же

Re: Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 14:53:28
zub
Всё не может знать о всём. Голова ученика знает где учится, ногам это знать не обязательно, они ходят туда куда скажет голова))
ИМХО всё бить на "атомарные" состовляющие и из них уже составлять нужные структуры - вполне логичный подход

Re: Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 14:56:19
Brainenjii
но почему-то в том же C# я могу такое осуществить без особых проблем, просто поместив файлы с описанием класса и ученика в один Namespace. Сейчас попробую накидать вариант с головой, по-моему оно тоже не пройдёт ^_^

Добавлено спустя 13 минут 9 секунд:
Ну да, старый добрый unit3.pas(8,27) Fatal: Circular unit reference between Unit3 and Unit1
Unit1:
Код: Выделить всё
Unit Unit1;
Interface
Uses
  Classes, SysUtils, Unit2;
Type
TGrade = Class
  Private
    fPupils: TPupil;
  Public
    Property Pupils: TPupil Read fPupils;
End;
Implementation
End.

Unit2:
Код: Выделить всё
Unit Unit2;
Interface
Uses
  Classes, SysUtils, Unit3;
Type
TPupil = Class
  Private
    fHead: TPupilHead;
    fLegs: TPupilLegs;
  Public
    Property Head: TPupilHead Read fHead;
    Property Legs: TPupilLegs Read fLegs;
End;
Implementation
End.

Unit3:
Код: Выделить всё
Unit Unit3;
Interface
Uses
  Classes, SysUtils, Unit1;
Type
TPupilHead = Class
Private
  fGrade: TGrade;
  Public
    Property Grade: TGrade Read fGrade;
End;
Implementation
End.

Почему-то порочной считается именно сама циклическая связь между классами... Но ведь, блин, она очевидна и правильна >_<

Re: Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 15:25:21
zub
>>Но ведь, блин, она очевидна и правильна >_<
а в каком порядке юниты инициализировать? Цикличные ссылки даже если их вынести за Implementation - зло, нераз напарывался на ситуацию когда безобидная правка исходников меняла порядок инициализации юнитов, да и вообще когда всё друг на дружку ссылается в uses - подцепил "старый" модуль в новый проект, и не заметил как у тебя весь "старый" проект подцепился к новому.

Добавлено спустя 4 минуты 12 секунд:
В предидущем посте ты не избавился от цикличности, ты ее вместо 2х цацикленных модулей разнес по 3м. нужно от нее избавляться
Код: Выделить всё
Unit UnitA;

{$mode objfpc}{$H+}

Interface

Uses
  Classes, SysUtils;

Type

{ ClassB }

ClassA = Class
  Public
    // тут абстрактный предок класса B с нужным функционалом
End;

Implementation

End.

Код: Выделить всё
Unit UnitB;

{$mode objfpc}{$H+}

Interface

Uses
  Classes, SysUtils;

Type

{ ClassB }

ClassB = Class
  Public
    // тут абстрактный предок класса А с нужным функционалом
End;

Implementation

End.

Re: Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 15:43:30
Brainenjii
в идеале хотелось бы, чтобы модули, установленные в одном Namespace, читались как один...
Что-то вроде
School:
Код: Выделить всё
Unit School;
Interface
Uses
  fgl;

Type TGrade = Class;
Type TGrades = Specialize TFPGList<TGrade>;

Type TPupil = Class;
Type TPupils = Specialize TFPGList<TPupil>;

Implementation

End.

School.Grade:
Код: Выделить всё
Unit School.Grade;
Interface
Uses
  Classes, SysUtils;
Type TGrade = Class
  Strict Private
    fPupils: TPupils;
  Public
    Property Pupils: TPupils Read fPupils;
End;
Implementation
End.

School.Pupil:
Код: Выделить всё
Unit School.Pupil;
Interface
Uses
  Classes, SysUtils;
Type TPupil = Class
  Strict Private
    fGrade: TGrade;
  Public
    Property Grade: TGrade Read fGrade;
End;
Implementation
End.

И всё. Компилятор проходя по модулям объединяет модули с точкой в названии в один "псевдо" файл. Можно ему даже помочь чем-то вроде
Код: Выделить всё
Unit School;
{$namespace school.grade}
{$namespace school.pupil}
Interface
Uses fgl;
Type TGrade = Class;
Type TGrades = Specialize TFPGList<TGrade>;
Type TPupil = Class;
Type TPupils = Specialize TFPGList<TPupil>;
Implementation
End.
объединяет так, что и Interface, и Implementation части - вначале идут из родительского класса, потом из всех остальных, без особой важности в каком порядке... И всё! И кучу всего сразу можно делать - и обращаться к приватным полям классов в одном пространстве имён, и Strict Private обретёт смысл и вообще... Классно же было бы, и удобно...

Re: Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 16:04:32
stikriz
Все дело в том, что ученик - это один объект, класс - это другой, а расписание или история, где он учился - это третий. Вот тогда все встает на свои места. Если бы это было в БД, то третья нормальная форма обязала бы нас сделать еще одну таблицу с двумя форейгнкеями на учеников и на классы.

Re: Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 16:15:57
Brainenjii
история это конечно круто... Но проблему, толком, не решает... А дополненная реализация namespace'ов - решила бы...
Я понимаю, если бы этого нигде не было и всегда говорили бы "фи"... Но, блин, в современных языках такое реализуется довольно просто и выгода очевидена и велика... А уж как тесты бы славно легли на такой механизм....

Re: Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 16:18:55
stikriz
Это только вначале паскаль кажется ущербным. Потом понимаешь, что так оно наиболее логично. Кстати, паттерны поизучайте - меньше будет таких извратов.

Re: Отношения многие ко многим

СообщениеДобавлено: 28.06.2012 16:27:10
Brainenjii
Ещё раз.
Есть класс, он должен иметь список учеников. Есть ученик, которому было бы очень неплохо знать, в каком классе он учится.
Что извращённого в желании реализовать такое? Какой анти-паттерн существует для такой структуры?
З.Ы. и 3 нормальная форма не имеет никакого отношения к озвученной проблеме