(Delphi) вопрос по ООП

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by xophet, 9 Jul 2011.

  1. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    Всем привет!
    Начал я значится учить ООП.
    Пробую написать программу с использованием ООП, и возник следующий вопрос:
    Есть объект (назовем А), который я планирую в дальнейшем использовать как законченый объект.

    Есть поток, который я планирую создавать, запускать, останавливать внутри объекта А.

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

    В случае с вложенными классами ответ видится простой:
    поток - вложенный класс объекта А и в нужный момент вызывает метод Add объекта A в котором прописаны
    Code:
    CriticalSection.Enter;
    StringList.add;
    CriticalSection.Leave;
    Внимание вопрос:
    Как бы Вы вышли из создавшейся ситуации, учитывая что Delphi 7 версии и вложенные классы в нем отсутствуют.

    Спасибо.
     
    #1 xophet, 9 Jul 2011
    Last edited: 9 Jul 2011
  2. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    937
    Likes Received:
    162
    Reputations:
    27
    Если правильно понял суть вопроса, то в потоке создай поле, в котором будет храниться ссылка на главный обьект. То есть при создании потока из главного обьекта сразу заноси в него ссылку на самой обьект. Потом по этой ссылке можешь выполнять какие нибудь действия с обьектом из потока.
     
  3. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    не получается таким образом, ведь мне нужно:
    Creator = class (TObject)
    public
    Thread1:Thread; //в этом месте компилятор еще не знает, о существовании класса Thread
    end;

    Thread = class (TThread)
    public
    a:Creator;
    end;

    Ну а если объявление Thread перенести выше, то комплятор не знает класса Creator
     
    #3 xophet, 10 Jul 2011
    Last edited: 10 Jul 2011
  4. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    937
    Likes Received:
    162
    Reputations:
    27
    Пишите так:
    Code:
    [B]Creator = class;[/B]
    
    Thread = class(TThread)
    public 
      a: Creator;
    end;
    
    Creator = class(TObject)
    public
      Thread1: Thread;
    end;
     
  5. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    Code:
    [B]Creator = class;[/B]
    
    Thread = class(TThread)
    public 
      a: Creator; //тут выдаст ошибку "Undeclared identifier Creator"
    end;
    
    Creator = class(TObject)
    public
      Thread1: Thread; //если поменять местами классы, то тут выдаст ошибку "Undeclared identifier Thread"
    end;
     
  6. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    937
    Likes Received:
    162
    Reputations:
    27
    Попробуй создать в Delphi 7 новый проект.
    Далее над
    Code:
    TForm1 = class(TForm)
    но ниже раздела type напиши
    Code:
      Creator = class;
    
      Thread = class(TThread)
      public
        a: Creator;
      end;
    
      Creator = class(TObject)
      public
        Thread1: Thread;
      end;
    Только что проверил, все нормально компилируется.
     
    1 person likes this.
  7. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    Cпасибо, заработало!!!
     
  8. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    Еще вопрос возник: как объекту передать ссылку на самого себя?
    В Java это делается при помощи ключевого слова this.
    А в Delphi?
     
  9. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    937
    Likes Received:
    162
    Reputations:
    27
    Ключевое слово Self.
     
  10. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    Во, отлично, спасибо!
     
  11. GhostOnline

    GhostOnline Active Member

    Joined:
    20 Dec 2008
    Messages:
    723
    Likes Received:
    110
    Reputations:
    22
    Использование в программе классов еще не означает ООП (с)
    Этот твой
    класс утилитный, да еще и с наследованием от библиотечного.
    Помещать в него логику, или ссылки на "неутилитные" (т.е. реализующие логику программы) - дурная практика(небось все в Execute написал, ага?). У тебя сейчас класс А знает про класс Б, а класс Б знает про класс А, да еще и с указанием конкретных типов - получаем практически любовь до гроба.
    Куда проще 1(!) раз написать наследника от TThread, которому в конструктор передавать ссылку на метод который будет выполняться в потоке и все.
    Например в твоем классе А есть метод Foo который нужно вынести в поток, тогда
    var thread: TMyThread;
    .................
    thread := TMyThread.Create(Foo)
    теперь метод Foo хоть и выполняется в отдельном треде, но имеет доступ к контексту класса А - к его полям, методам и т.д. И даже не надо открывать к членам класса доступ - все можно оставить приватным.
    Вообще способ создания вторичных потоков в борланде придумали достаточно оригинальный, а многие дельфисты идут у них на поводу. Но вроде бы в ХЕ они "уже" исправились :)

    PS не сочтите за археологию, хотел ответить на этот пост еще при актуальности темы, но потом внезапно ушел в отпуск =)
     
  12. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    Тема ни в коем разе актульности не утратила, спасибо за помощь!
     
  13. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    Значится добрался до своего проекта,
    и возник следующий вопрос "Как передать ссылку на метод класса?":

    Code:
    TChecker = class
      private
        procedure Check;
      public
    ....
        procedure run;
      end;
    
    TCheckThread = class (TgsvThread)
      private
        Check:TProcedure;
      public
      protected
        constructor Create(Check:TProcedure);
        procedure Execute; override; 
      end;
    
    procedure TChecker.Check;
    begin
    .....
    end;
    При попытке написать CHK:=TCheckThread.Create(Check)
    выдает ошибку:
    [Error] Check.pas(308): Incompatible types: 'regular procedure and method pointer'

    Если же сделать

    Code:
    TChecker = class
      private
        Check:TProcedure;
      public
    ....
        procedure run;
      end;
    
    TCheckThread = class (TgsvThread)
      private
        Check:TProcedure;
      public
      protected
        constructor Create(Check:TProcedure);
        procedure Execute; override; 
      end;
    
    procedure TChecker.Check; //то здесь выбивает ошибку (см ниже)
    begin
    .....
    end;
    [Error] Check.pas(325): Declaration of 'Check' differs from previous declaration

    А если сделать

    Code:
    
    TChecker = class
      private
        Check:TProcedure;
      public
    ....
        procedure run;
      end;
    
    
    procedure Check;
    begin
    .....
    end;
    То можно TChecker.Check:=Check, но процедура Check, естественно, не знает ничего о полях и методах TChecker

    А так:
    Code:
    CH:=@TChecker.Check;
    CHK:=TCheckThread.Create(CH);
    
    Вылазит "Acces violation" при обращении к полям и методам класса (что опять же логично).

    Где я что упускаю?

    Delphi 7
     
    #13 xophet, 23 Jul 2011
    Last edited: 23 Jul 2011