Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.04.18;
Скачать: CL | DM;

Вниз

Как в методе получить указатель на перем-ю, которая вызвала метод   Найти похожие ветки 

 
Mishenka   (2004-03-31 00:08) [0]

Есть class у которого есть метод. А также есть переменные с типом этого класса. Как в этом методе получить указатель на переменную, которая вызвала этот метод?


 
eLVik ©   (2004-03-31 00:30) [1]

self
А тебе это зачем?


 
Mishenka   (2004-03-31 00:56) [2]

Да я вот так и написал Self. Но при попытке обратиться к одному из свойств Self вызывает ошибку EAccessViolation :(((


 
Defunct ©   (2004-03-31 01:00) [3]

Self это малость не то. Self указывает на объект с полями которого работает текущий метод. А определить кто вызвал этот метод можно только в том случае, если передать указатель на вызывающий объект в параметрах метода. Обычно это Sender:TObject.

А далее уже в теле метода смотреть:

If Sender is (какой-то класс) Then Sender as (какой-то класс) Do


 
Defunct ©   (2004-03-31 01:04) [4]

> Но при попытке обратиться к одному из свойств Self вызывает ошибку EAccessViolation :(((

А вот это уже совсем интересно. Если возникает ошибка только при обращении к однону из свойств, значит неверно описано свойство.


 
Mishenka   (2004-03-31 01:55) [5]


> Defunct ©   (31.03.04 01:04) [4]
> А вот это уже совсем интересно. Если возникает ошибка только
> при обращении к однону из свойств, значит неверно описано
> свойство.

Ну просто только к одному и обращался :)))


> If Sender is (какой-то класс) Then Sender as (какой-то класс)Do

А если имя класса неизвестно, а известно лишь что это один из потомков данного класса, то можно ли обойтись без перебора всех классов?


 
Rouse_ ©   (2004-03-31 02:13) [6]

> Как в этом методе получить указатель на переменную, которая
> вызвала этот метод?

Банально, переменная не может вызвать метод (если не опускаться до полиморфии...)

> Если возникает ошибка только при обращении к однону из свойств,
> значит неверно описано свойство

Также может быть неверно описан сам объект... (как раз таки пика в сторону оператора AS)

> А если имя класса неизвестно, а известно лишь что это один
> из потомков данного класса, то можно ли обойтись без перебора
> всех классов?

Без вызова методов наследников можно...


 
Mishenka   (2004-03-31 02:23) [7]


> Rouse_
> Без вызова методов наследников можно...

А как?


 
Германн ©   (2004-03-31 02:42) [8]

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


 
Mishenka   (2004-03-31 02:48) [9]


> Германн ©   (31.03.04 02:42) [8]

Это всё замечательно, только  там где Sender as как это всё написать и каким классом обозвать. Если писать класс родителя, то выдаёт ошибку.


 
Германн ©   (2004-03-31 03:09) [10]

2 Mishenka   (31.03.04 02:48) [9]
Во-первых какую ошибку?
Во-вторых, лучше бы привести фрагмент кода, а не ограничиваться общими словами, которые мы можем понимать по-разному.


 
Mishenka   (2004-03-31 03:37) [11]

Ошибка EInvalidCast тобишь недопустимое преобразование типов с помощью оператора as...


 
Германн ©   (2004-03-31 03:52) [12]

А где "фрагмент кода"?
EInvalidCast - действительно та самая ошибка, но где и как она возникает?
Без кода - это "пойди туда, не знаю куда. принеси то, не знаю что"!


 
Mishenka   (2004-03-31 04:23) [13]

Лови код:

TMainClass=class(TObject)
   Width,Height:Integer;
   procedure GetWH(Sender: TObject);
   function GetName:string; virtual; abstract;

 end;

TClassA=class(TMainClass)
   propA:Integer;
   function GetName:string; override;
 end;

 TClassB=class(TMainClass)
   propB:Integer;
   function GetName:string; override;
 end;

 TClassC=class(TMainClass)
   propC:Integer;
   function GetName:string; override;
 end;

...

procedure TMainClass.GetWH(Sender: TObject);
var Ob:TMainClass;
begin
  Ob:=Sender as Sender.ClassName; {здесь происходит EInvalidCast
    with Form2 do
    begin
       Edit1.Clear;
       Edit2.Clear;
       ShowModal;
       if ModalResult=mrOk then
       begin
            Form1.ListBox1.Items.AddObject(Sender.GetName,Ob);
       end;
    end;
end;

function TClassA.GetName:string;
begin
    GetName:="A";
end;

function TClassB.GetName:string;
begin
    GetName:="B";
end;

function TClassC.GetName:string;
begin
    GetName:="C";
end;



 
ЮЮ ©   (2004-03-31 06:56) [14]

>Sender as Sender.ClassName

ClassName - это стринг
Ob := TMainClass(Sender);

А проще переписать сам TMainClass так:

TMainClass = class;
TMainClass = class(TObject)
  Width,Height:Integer;
  procedure GetWH(Sender: TMainClass);
  function GetName:string; virtual; abstract;
end;


 
ЮЮ ©   (2004-03-31 06:59) [15]

P.S.
>Form1.ListBox1.Items.AddObject(Sender.GetName,Ob);
Form1.ListBox1.Items.AddObject(Ob.GetName,Ob);


 
Гаврила   (2004-03-31 09:25) [16]

Не совсем понятный, и странный код
а где вызывается TMainClass.GetWH?
И как ? И что передается в качестве параметра Sender ?

ТО есть я правильно понял, что параметром в метод GetWH передается другой экземпляр класса TMainClass(или потомка) ?
В противном случае параметр Sender явно лишний.

Приведи код вызова метода


 
Palladin ©   (2004-03-31 09:28) [17]

Sender as FindClass(Sender.ClassName)

перед этим искомый класс должен быть зарегистрирован RegisterClass


 
Palladin ©   (2004-03-31 09:44) [18]

:) здорово я пошутил :)

ответ не принимать в расчет ибо подобное приведение ни к чему не приведет


 
Mishenka   (2004-03-31 16:31) [19]

Ну вот вам код вызова метода:


procedure TForm1.Button1Click(Sender: TObject);
var A:TClassA;
begin
    A.GetWH(A);
end;

procedure TForm1.Button2Click(Sender: TObject);
var B:TClassB;
begin
    B.GetWH(B);
end;

procedure TForm1.Button3Click(Sender: TObject);
var C:TClassC;
begin
    C.GetWH(C);
end;


 
Mishenka   (2004-03-31 22:40) [20]

Ну что? Есть идеи?


 
ЮЮ ©   (2004-04-01 03:20) [21]

Убрать параметр совсем

Form1.ListBox1.Items.AddObject(GetName, Self);

P.S. Использование Form1 и Form2 в коде метода TMainClass, IMHO, не очень уместно


 
LexusR ©   (2004-04-01 06:17) [22]


procedure TMainClass.GetWH(Sender: TObject);
begin
   with TForm2.Create(nil) do
   begin
      Edit1.Clear;
      Edit2.Clear;
      ShowModal;
      if ModalResult=mrOk then
      begin
           Self.Width  := StrToInt(Edit1.text);
           Self.Height := StrToInt(Edit2.Text);
           Form1.ListBox1.Items.AddObject(Self.GetName,Self);
      end;
      Free;
   end;
end;
......
procedure TForm1.Button1Click(Sender: TObject);
var A:TClassA;
begin
   A := TClassA.Create;
   A.GetWH(A);
   A.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var B:TClassB;
begin
   B := TClassB.Create;
   B.GetWH(B);
   B.Free;
end;

procedure TForm1.Button3Click(Sender: TObject);
var C:TClassC;
begin
   C := TClassC.Create;
   C.GetWH(C);
   C.Free;
end;



 
LexusR ©   (2004-04-01 06:18) [23]

и как сказал ЮЮ  параметр Sender лишний


 
Defunct ©   (2004-04-01 08:54) [24]

Что-то я не понял в чем прикол.
Как первоначальный вопрос Mishenka   (31.03.04 00:08), стыкуется с этим кодом: Mishenka   (31.03.04 16:31) [19]?

Зачем вам вызывающий объект? Ведь в данном случае метод вызывает объект класса TForm1.

Ну ладно умом россию не понять.


 
Mishenka   (2004-04-01 22:41) [25]


> LexusR ©   (01.04.04 06:17) [22]

Круто! Так всё работает! Спасибо.
Только у меня ещё одна фигня получилась.
Нужно чтобы по DblClick на ListBox выводилось имя объекта.
Пишу:

procedure TForm1.ListBox1DblClick(Sender: TObject);
var ClassMain:TMainClass;
begin
    with ListBox1 do
    ClassMain:=Items.Objects[ItemIndex] as TMainClass;
    ShowMessage(ClassMain.ClassName);
end;


Опять вылазит ошибка EInvalidCast. Чё-то я опять торможу...


 
Гаврила   (2004-04-01 23:02) [26]

>>LexusR ©   (01.04.04 06:17) [22]

Добавили Self в объекты строкового списка, а потом этот самый Self грохнули (см вызов метода GetWH)

так нельзя

вообще, (к автору ветки) - организуйте структуру кдассов - вызовов по другому, то, что тут представлено - это чекрез одно место.
скорее всего это должны быть методы формы, а не доп. классов

Блин !!!! А создать экземпляры классов ?
разумеется, какое то методы можно вызывать и не создавая экземпляры (Self будет равен nil, пример - метjд Free )
Но это отночится только к статическим методам, не использующим поля-свойства


 
Гаврила   (2004-04-01 23:07) [27]

Последний абзац  моего поста [26] прошу не рассматривать, я его написал прежде чем увидел ответ [22]

автору
если вы настаиваете на именно такой  организации, не разрушайте экземпляры TClassA (и прочих в случае показа модальной формы с результатом MrOk). При этои не забудьте разрушить их перед очисткой Form1.ListBox1.Items


 
Гаврила   (2004-04-01 23:09) [28]

function TMainClass.GetWH(Sender: TObject): Boolean;
begin
  with TForm2.Create(nil) do
  begin
     Edit1.Clear;
     Edit2.Clear;
(Result:=ShowModal = MrOk);
     
     if Result then
     begin
          Self.Width  := StrToInt(Edit1.text);
          Self.Height := StrToInt(Edit2.Text);
          Form1.ListBox1.Items.AddObject(Self.GetName,Self);
     end;
     Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var A:TClassA;
begin
  A := TClassA.Create;
  if not A.GetWH(A) then
    A.Free;
end;


 
Mishenka   (2004-04-02 14:50) [29]

Это всё зачмечательно, только я так и не понял что делать в DblClick:
procedure TForm1.ListBox1DblClick(Sender: TObject);
var ClassMain:TMainClass;
begin
   with ListBox1 do
   ClassMain:=Items.Objects[ItemIndex] as TMainClass;
   ShowMessage(ClassMain.ClassName);
end;

выдаёт ошибку EInvalidCast и всё тут.


 
Mishenka   (2004-04-02 21:16) [30]

Может всё-таки есть какие-нибудь предложения?


 
Mishenka   (2004-04-02 21:16) [31]

Может всё-таки есть какие-нибудь предложения?


 
Defunct ©   (2004-04-02 23:23) [32]

Вот для пущей наглядности:

 TMainClass = class(TObject)
   Width,Height:Integer;
   function GetName:string; virtual; abstract;
 End;

 TClassA=class(TMainClass)
   propA:Integer;
   function GetName:string; override;
 end;

TClassB=class(TMainClass)
  propB:Integer;
  function GetName:string; override;
end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

Function TClassA.GetName;
Begin
 Result := "Class A";
End;

Function TClassB.GetName;
Begin
 Result := "Class B";
End;

procedure TForm1.Button1Click(Sender: TObject);
begin
 ListBox1.AddItem("Class A", TClassA.Create);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 ListBox1.AddItem("Class B", TClassB.Create);
end;

procedure TForm1.ListBox1DblClick(Sender: TObject);
Var MainClass: TMainClass;
begin
 MainClass := ListBox1.Items.Objects[ListBox1.ItemIndex] as TMainClass;
 ShowMessage(MainClass.GetName);
end;


Никакого EInvalidCast нет.


 
Mishenka   (2004-04-04 17:07) [33]

Такдействительно ошибки нет, но нужночтобы объекты добавлялись через метод один метод, а не каждый в своей кнопке. Просто не пому, почему тут всё работает, а там нет ...



Страницы: 1 вся ветка

Текущий архив: 2004.04.18;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.024 c
3-1079539125
Санек
2004-03-17 18:58
2004.04.18
можно ли в ExpressQuantumGrid v4.5.2 писать данные в две строчики


14-1080319593
mmmaloy
2004-03-26 19:46
2004.04.18
Еще одна задача


14-1080426305
Thor
2004-03-28 01:25
2004.04.18
Попробуйте, не пожалеете :)


8-1073287268
serg128
2004-01-05 10:21
2004.04.18
как записать звук с микрофона? (по возможности на API)?


6-1077173208
GLFox
2004-02-19 09:46
2004.04.18
Network shares