Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Error: This call is only allowed for class methods.


der organist - Mi 17.12.08 22:10
Titel: Error: This call is only allowed for class methods.
Hi Leutz,
ich hab keine Ahnung, wie ich das fixen soll. Bisher hab ich das immer so (oder so ähnlich gemacht)...

Eine Unit (UMain), ruft ne andere (UAktion) auf.


Delphi-Quelltext
1:
Aktion.Mischen(Stapel);                    


Die Prozedur sieht so aus, weil die Unit so kurz is, schicke ich dir mal komplett...:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
unit UAktion;

interface

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, UKarte, StdCtrls;

type
  Aktion = class
  public
    procedure Mischen(var aStapel:Array of Karte);
end;


implementation

procedure Aktion.Mischen(var aStapel:Array of Karte);
var
  k, l, zufallskarte: Integer;
  bStapel:Array of Karte;
begin
  SetLength(bStapel,Length(aStapel));
  for k := 1 to Length(aStapel) do
    bStapel[k].Wert:=0;
  for k := 1 to 8 do begin
    for l := 1 to Length(bStapel) do begin
      zufallskarte:=Random(Length(bStapel))+1;
      if bStapel[zufallskarte].Wert=0 then
        bStapel[zufallskarte]:=aStapel[l];
    end;
  end;
  for k := 1 to 312 do
    aStapel[k]:=bStapel[k];
end;

end.


jaenicke - Mi 17.12.08 22:19

Nenn deine Klasse mal TAktion, dann kannst du eine Variable Aktion haben und dein erster Quelltext funktioniert. Ohne das T sieht das schrecklich aus, es ist Konvention, dass Klassenbezeichner mit einem T anfangen, jeder erwartet das.

Wenn du es als Klassenmethode haben willst, dann musst du schreiben

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
type
  TAktion = class
  public
    class procedure Mischen(var aStapel:Array of Karte);
  end;


implementation

class procedure TAktion.Mischen(var aStapel:Array of Karte);
Dann geht auch

Delphi-Quelltext
1:
TAktion.Mischen(Stapel);                    
Wobei du dann auch die Klasse weglassen kannst, wenn du das so machst, schließlich hat das so keinen Vorteil im Sinne der Objektorientierung.


der organist - Mi 17.12.08 22:22

und wenn du mir noch erklärst, wo der große Unterschied zwischen Class procdure und procedure ist, bin ich vollkommen glücklich :D.


jaenicke - Mi 17.12.08 22:26

Eine Klassenmethode bezieht sich auf die Klasse. D.h. in diesem Fall gehört die Methode mit "class procedure" zu der Klasse TAktion.

Wenn du jetzt zur Laufzeit ein Objekt vom Typ TAktion erzeugst, dann gehören Methoden ohne das class zu diesem Objekt. Wenn also in diesem Objekt Variablen bzw. Eigenschaften deklariert sind, dann greift eine solche Prozedur auf die zu, zu dessen Objekt im Speicher die Methode gehört.

Aus Klassenmethoden kannst du auf solche objektspezifischen Eigenschaften und Methoden nicht direkt zugreifen.

Mehr zum Thema findest du z.B. hier:
http://www.delphi-treff.de/sprachen/object-pascal/methoden/


Delete - Mi 17.12.08 22:30

Oder kurz gesagt: eine Klassenmethode braucht keine Instanz ;)


der organist - Mi 17.12.08 22:53

um das ganze also ohne classprozeduce zu nutzen muss ich also zuerst "TAktion" erzeugen, jo, hab ich vergessen....


jaenicke - Mi 17.12.08 23:24

Wenn du ohnehin kein objektorientiertes Vorgehen machst, dann kannst du auch schlicht sowas machen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
unit UAktion;

interface

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, UKarte, StdCtrls;

procedure Mischen(var aStapel: array of Karte);

implementation

procedure Mischen(var aStapel: array of Karte);
Und dann einfach Mischen oder UAktion.Mischen aufrufen ;-).