Конференция "KOL" » Вызов метода, чтоб его...
 
  • Dima (15.12.07 22:08) [0]
    Привет всем. Хотел написать небольшой компонент, основанный на объектах (надо для практики), но есть трабла. Помогите пожалуйста. Если я чего не понял, прошу не ругать :) Я начинающий. В целом компонент такого вида:

     PMyObj = ^TPMyObj;
     TOnMyObjEvent = procedure(Sender: PMyObj) of object;
     TMyObj = object( TObj )
       ... (тут всякие свойства...)
       destructor Destroy; virtual;
     end;

     PMainComp = ^TMainComp;
     TMainComp = object(TObj)
     private
     FOnUpdate: TOnMyObjEvent;
     ...
     public
       property OnUpdate: TOnMyObjEvent read FOnUpdate write FOnUpdate;
     
     end;
     
     
    Есть некоторая процедура внутри TMainComp, которая создаёт и формирует экземпляр TMyObj (при помощи New(MyObj, Create), MyObj - PMyObj), а затем вызывает метод OnUpdate(MyObj), внутри которого идёт обращение к свойствам объекта. Как вы уже, наверное, догадались, я успешно получаю обухом по голове :) а почему, понять не в состоянии. Может, от того, что целый день парюсь, но дела не меняются - внутри метода стоит только обратиться к любому свойству MyObj, как прога вылетает. Почему?
  • Vladimir Kladov © (15.12.07 22:14) [1]
    Код присваивания обработчика событию, и код вызова - не приведены. (Наверняка опять различие ординарной процедуры и метода объекта, но не на 100% - здесь-то оно зачем. А может вы просто Sender и Self перепутали. Без кода непонятно).
  • Dima (15.12.07 22:51) [2]
    Ну вот как-то так:
    type
     PMyObj = ^TMyObj;
     TOnMyEvent = procedure(Sender: PMyObj) of object;
     TMyObj = object( TObj )
       Name: string;
       private
         FOnUpdate: TOnMyEvent;
       procedure SetOnUpdate(const Value: TOnMyEvent);
       public
         destructor Destroy; virtual;
         property OnUpdate: TOnMyEvent read FOnUpdate write SetOnUpdate;
     end;

     PMyComp = ^TMyComp;
     TMyComp = object(TObj)
     protected
     private
       FOnUpdate: TOnMyEvent;
       procedure SetOnUpdate(const Value: TOnMyEvent);
     public
       FMyObj: PMyObj;
       destructor Destroy; virtual;
       property OnUpdate: TOnMyEvent read FOnUpdate write SetOnUpdate;
       procedure Go;
     end;

    function NewMyComp: PMyComp;

    implementation

    function NewMyComp: PMyComp;
    begin
     New(Result, Create);
     New(Result.FMyObj, Create);
     Result.FMyObj.Name := 'MyComp Name';
    end;

    procedure TMyObj.SetOnUpdate(const Value: TOnMyEvent);
    begin
     FOnUpdate := Value;
    end;

    procedure TMyComp.Go;
    begin
     Self.FMyObj.OnUpdate := Self.FOnUpdate;
     if Assigned(Self.FMyObj.OnUpdate) then
       Self.FMyObj.OnUpdate(@Self.FMyObj);
    end;

    procedure TMyComp.SetOnUpdate(const Value: TOnMyEvent);
    begin
     FOnUpdate := Value;
    end;

    end.



    Далее в программе:
    procedure OnUpdate(Sender: PMyObj);
    begin
     ShowMessage(Sender.Name);
    end;

    procedure TForm1.Button1Click(Sender: PObj);
    var
     MyComp: PMyComp;
    begin
     MyComp := NewMyComp;
     MyComp.OnUpdate := TOnMyEvent(MakeMethod(nil, @OnUpdate) );
     MyComp.Go;

     MyComp.Free;
    end;

  • Dima (15.12.07 22:54) [3]
    Это только пример, я специально наваял, но принцип того, что хочу сделать, видно.
  • Дмитрий К © (15.12.07 23:24) [4]
    У меня вот так заработало. А почему, сами разбирайтесь, либо пусть кто другой объяснит. Я в теории - не очень.

    program project1;
    uses KOL;

    type
    PMyObj = ^TMyObj;
    TOnMyEvent = procedure(Sender: PMyObj) of object;
    TMyObj = object( TObj )
      Name: string;
      private
        FOnUpdate: TOnMyEvent;
      procedure SetOnUpdate(const Value: TOnMyEvent);
      public
    //     destructor Destroy; virtual;
        property OnUpdate: TOnMyEvent read FOnUpdate write SetOnUpdate;
    end;

    PMyComp = ^TMyComp;
    TMyComp = object(TObj)
    protected
    private
      FOnUpdate: TOnMyEvent;
      procedure SetOnUpdate(const Value: TOnMyEvent);
    public
      FMyObj: PMyObj;
    //   destructor Destroy; virtual;
      property OnUpdate: TOnMyEvent read FOnUpdate write SetOnUpdate;
      procedure Go;
    end;

    function NewMyComp: PMyComp;
    begin
    New(Result, Create);
    New(Result.FMyObj, Create);
    Result.Add2AutoFree(Result.FMyObj);
    Result.FMyObj.Name := 'MyComp Name';
    end;

    procedure TMyObj.SetOnUpdate(const Value: TOnMyEvent);
    begin
    FOnUpdate := Value;
    end;

    procedure TMyComp.Go;
    begin
    Self.FMyObj.OnUpdate := Self.FOnUpdate;
    if Assigned(Self.FMyObj.OnUpdate) then
      Self.FMyObj.OnUpdate(Self.FMyObj);
    end;

    procedure TMyComp.SetOnUpdate(const Value: TOnMyEvent);
    begin
    FOnUpdate := Value;
    end;

    procedure OnUpdate(Dummy, Sender: PMyObj);
    begin
    ShowMessage(Sender.Name);
    end;

    procedure Button1Click(Dummy, Sender: PObj);
    var
    MyComp: PMyComp;
    begin
    MyComp := NewMyComp;
    MyComp.OnUpdate := TOnMyEvent(MakeMethod(nil, @OnUpdate) );
    MyComp.Go;

    MyComp.Free;
    end;

    var form, btn: PControl;

    begin
     form := newform(nil, 'test');
     btn := newbutton(form,'click').ResizeParent;
     btn.OnClick := TOnEvent(MakeMethod(nil, @Button1Click));

     run(Form);

    end.

  • Vladimir Kladov © (16.12.07 08:31) [5]
    Это именно то, что я и подозревал как №1.
    procedure OnUpdate(Dummy, Sender: PMyObj);

    Как я в описании Соль заметил, выросло поколение (хороших, но неграмотных) программеров, которых инфиксная запись и отсутствия явной передачи параметра-объекта сбивает с толку. Не пишут параметр, значит его как бы и нет.
  • Dima (16.12.07 09:17) [6]
    Спасибо всем, я понял в чём дело :)
 
Конференция "KOL" » Вызов метода, чтоб его...
Есть новые Нет новых   [134431   +10][b:0][p:0.002]