Autor Beitrag
Elrond
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 01.01.09 19:42 
Hallo und euch allen erstmal ein frohes neues Jahr. Hier ist mein Problem. Seit einigen Monaten arbeite ich mit Delphi 5. Abgesehen von den GUI-Komponenten habe ich bisher prozedural programmiert. Jetzt habe ich mit OOP begonnen. Dabei möchte ich mit Objekten arbeiten, deren Typ bei der Compilation noch nicht bekannt ist und erst während der Laufzeit festgelegt wird.

Ich habe nun zwei allgemeine Variablen definiert.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
var
  p1,p2: TObject;

Desweiteren gibt es zwei Klassen:

TObjekt1=Class(TObject)
  private
   sig:string;
  public
   procedure init; virtual;abstract;
   ...
end;

TObjekt2 = Class(TObjekt1)
  private
   re,im:Extended;
  public
   procedure init(re_,im_:Extended); overload;
   ...
end;


In Abhängigkeit von gewissen Eingaben mache ich dann folgendes:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
p1:=TObjekt2.Create; (Klappt! Compiler sagt: Erstelle Instanz von TObjekt2 mit abstrakten Methoden)
p2:=TObjekt2.Create; (Hier ebenso)
p1.init(r1,r2); (...und hier steigt der Compiler aus mit: "undefinierter Bezeichner init")
p2.Init(r3,r4);


r1,r2,r3,r4 sind Extended-Variablen, es wurde ein Objekt vom Typ TObjekt2 erzeugt, der Pointer wurde p1 zugewiesen, also verweist p1 auf ein Objekt vom Typ TObjekt2 und müsste demnach auch die Methode init kennen.
Übrigens, wenn ich p1 nicht als Variable vom Typ TObject sondern vom Typ TObjekt2 deklariere, dann funktioniert es, hilft mir aber nicht weiter. Ich möchte während der Laufzeit verschiedene Typen von Objekten instanzieren und dann im weiteren jeweils über p1 und p2 ansprechen.

Wo liegt der Fehler?

Schon mal Danke im voraus.

Elrond.

Moderiert von user profile iconGausi: Delphi-Tags hinzugefügt
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 01.01.09 20:57 
Falls niemand den Fehler entdeckt, wäre ich auch schon damit zufrieden, wenn mir jemand einen Tipp geben könnte, um das zu erreichen, was ich möchte.

Allgemein: Ich möchte verschiedene Klassen C1, C2,... definieren, die jeweils gleichnamige Methoden besitzen, zum Beispiel M. Dann möchte ich p.M aufrufen und vorher während der Laufzeit entscheiden, ob p auf ein Objekt vom Typ C1, C2 und so weiter zeigt.

Thx.

Elrond.
UGrohne
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Do 01.01.09 20:59 
Die Typ-Deklaration Deiner Variable muss schon Kenntnisse über die Methoden haben, die Du aufrufen möchtest und genau diese Kenntnis besitzt die Klasse object natürlich nicht. In Deinem Fall würde es aufgrund der Vererbung von TObjekt1 nach TObjekt2 ausreichen, wenn Du Deine Variablen als TObjekt1 deklarierst.

Eine bessere Alternative stellt allerdings die Verwendung von Interfaces dar, die Dir den Bauplan aller Klassen vereinheitlicht. Deine Variablen sind dann vom Typ des Interfaces und kennen die Methode Init:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
var
  p1,p2: IObject;
IObject = interface
  procedure init;
end;

TObjekt1=Class(TObject, IObject)
  private
   sig:string;
  public
   procedure init; virtual;abstract;
   ...
end;

TObjekt2 = Class(TObjekt1, IObject)
  private
   re,im:Extended;
  public
   procedure init(re_,im_:Extended); overload;
   ...
end;
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 01.01.09 21:24 
Nur dass im Interface bzw. der Oberklasse die Methode init auch mitsamt der Parameter definiert werden muss. Denn sonst kennt der Compiler die Parameter ja nicht. ;-)
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 01.01.09 21:29 
user profile iconUGrohne hat folgendes geschrieben Zum zitierten Posting springen:
Die Typ-Deklaration Deiner Variable muss schon Kenntnisse über die Methoden haben, die Du aufrufen möchtest und genau diese Kenntnis besitzt die Klasse object natürlich nicht. In Deinem Fall würde es aufgrund der Vererbung von TObjekt1 nach TObjekt2 ausreichen, wenn Du Deine Variablen als TObjekt1 deklarierst.

Eine bessere Alternative stellt allerdings die Verwendung von Interfaces dar, die Dir den Bauplan aller Klassen vereinheitlicht. Deine Variablen sind dann vom Typ des Interfaces und kennen die Methode Init:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
var
  p1,p2: IObject;
IObject = interface
  procedure init;
end;

TObjekt1=Class(TObject, IObject)
  private
   sig:string;
  public
   procedure init; virtual;abstract;
   ...
end;

TObjekt2 = Class(TObjekt1, IObject)
  private
   re,im:Extended;
  public
   procedure init(re_,im_:Extended); overload;
   ...
end;


Hallo Uwe, danke für Deine Antwort. Also ich habe jetzt mal wie vorgeschlagen p als TObjekt1 deklariert, bekomme jetzt aber die Fehlermeldung "Zu viele Parameter" beim Aufruf von p.init(r1,r2). Irgendwie habe ich den Eindruck, dass die Variable p weiterhin auf ein Objekt vom Typ Objekt1 zeigt, obwohl der Compiler bestätigt, dass eine Instanz von Objekt2 erzeugt und der Variable p zugewiesen wurde.

Elrond
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 01.01.09 21:33 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Nur dass im Interface bzw. der Oberklasse die Methode init auch mitsamt der Parameter definiert werden muss. Denn sonst kennt der Compiler die Parameter ja nicht. ;-)


...und eben das ist das Problem. Nehmen wir einmal an, dass Init als Methode von TObjekt2 zwei Parameter hat, als Methode von TObjekt3 7 Parameter und als Methode von TObjekt4 Null Parameter. Ich möchte zur Laufzeit entscheiden, ob p auf ein Objekt vom Typ TObjekt2, TObjekt3 oder TObjekt4 zeigt und init dann mit der entsprechenden Parameterzahl aufrufen.

Elrond
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 01.01.09 21:45 
Dann kannst du ein array of const als einen einzelnen Parameter nehmen, aufrufen kannst du das dann wie den Format Befehl von Delphi.
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 01.01.09 21:59 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Dann kannst du ein array of const als einen einzelnen Parameter nehmen, aufrufen kannst du das dann wie den Format Befehl von Delphi.


Das Problem ist, dass p auch nach der Zuweisung p:=TObjekt2.Create immer noch auf ein Objekt vom Typ TObjekt1 zu zeigen scheint und nicht auf ein Objekt vom Typ TObjekt2, obwohl gerade so ein Objekt laut Compiler erzeugt wurde. Irgendwie habe ich den Eindruck, als ob p statisch wäre, so wie im alten Objektmodell (type = object) und nicht dynamisch wie im neuen Objektmodell (type=class) eigentlich der Fall sein sollte. Bei mir macht sich so langsam der Frust breit... :(

Elrond
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 01.01.09 22:17 
user profile iconElrond hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Dann kannst du ein array of const als einen einzelnen Parameter nehmen, aufrufen kannst du das dann wie den Format Befehl von Delphi.


Das Problem ist, dass p auch nach der Zuweisung p:=TObjekt2.Create immer noch auf ein Objekt vom Typ TObjekt1 zu zeigen scheint und nicht auf ein Objekt vom Typ TObjekt2, obwohl gerade so ein Objekt laut Compiler erzeugt wurde. Irgendwie habe ich den Eindruck, als ob p statisch wäre, so wie im alten Objektmodell (type = object) und nicht dynamisch wie im neuen Objektmodell (type=class) eigentlich der Fall sein sollte. Bei mir macht sich so langsam der Frust breit... :(

Elrond


Mein Verdacht hat sich bestätigt. Ich habe jetzt init überall mit identischen Parametern deklariert, so dass der Compiler das schluckt. Es gibt nun wie erwartet einen Laufzeitfehler, weil das Programm versucht, die abstrakte Methode init aus TObjekt1 aufzurufen und nicht die konkrete Methode init aus TObjekt2. Wie kann das sein? p:=TObjekt2.Create erzeugt ein Objekt vom Typ TObjekt2. :roll:

Elrond.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 01.01.09 22:18 
Das dürfte eigentlich nicht passieren, wie sieht denn der Code jetzt aus? Hast du die methode der Oberklasse mit override korrekt überschrieben?
Overload erzeugt nur eine weitere gleichnamige Methode, hat mit der in der Oberklasse aber nix zu tun.
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 01.01.09 22:30 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Das dürfte eigentlich nicht passieren, wie sieht denn der Code jetzt aus? Hast du die methode der Oberklasse mit override korrekt überschrieben?
Overload erzeugt nur eine weitere gleichnamige Methode, hat mit der in der Oberklasse aber nix zu tun.


Ja, ich habe override verwendet. Deklariere ich p als TObjekt1 => Laufzeitfehler, deklariere ich p als TObjekt2 läuft alles... :?

Elrond.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 01.01.09 22:54 
Ich sagte ja, poste doch mal den Code. Bei mir jedenfalls funktioniert das alles wie es soll: :nixweiss:
ausblenden volle Höhe 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:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
type
  TObjekt1=Class(TObject)
  private
    sig:string;
  public
    procedure init(re_,im_: Extended); virtualabstract;
    procedure init2(data: array of const); virtualabstract;
  end;

  TObjekt2 = Class(TObjekt1)
  private
    re,im:Extended;
  public
    procedure init(re_,im_:Extended); override;
    procedure init2(data: array of const); override;
  end;

  TForm118 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form118: TForm118;

implementation

{$R *.dfm}

procedure TForm118.Button1Click(Sender: TObject);
var
  p1: TObjekt1;
begin
  p1 := TObjekt2.Create;
  p1.init(12.322.4);
  ShowMessage(p1.sig);
  p1.init2([112.3122.4]);
  ShowMessage(p1.sig);
end;

{ TObjekt2 }

procedure TObjekt2.init(re_, im_: Extended);
begin
  re := re_;
  im := im_;
  sig := FloatToStr(re) + ' - ' + FloatToStr(im);
end;

procedure TObjekt2.init2(data: array of const);
begin
  re := data[0].VExtended^;
  im := data[1].VExtended^;
  sig := Format('Die Zahlen: %.2f und %.2f', data);
end;

end.
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 01.01.09 23:04 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Ich sagte ja, poste doch mal den Code. Bei mir jedenfalls funktioniert das alles wie es soll: :nixweiss:
ausblenden volle Höhe 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:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
type
  TObjekt1=Class(TObject)
  private
    sig:string;
  public
    procedure init(re_,im_: Extended); virtualabstract;
    procedure init2(data: array of const); virtualabstract;
  end;

  TObjekt2 = Class(TObjekt1)
  private
    re,im:Extended;
  public
    procedure init(re_,im_:Extended); override;
    procedure init2(data: array of const); override;
  end;

  TForm118 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form118: TForm118;

implementation

{$R *.dfm}

procedure TForm118.Button1Click(Sender: TObject);
var
  p1: TObjekt1;
begin
  p1 := TObjekt2.Create;
  p1.init(12.322.4);
  ShowMessage(p1.sig);
  p1.init2([112.3122.4]);
  ShowMessage(p1.sig);
end;

{ TObjekt2 }

procedure TObjekt2.init(re_, im_: Extended);
begin
  re := re_;
  im := im_;
  sig := FloatToStr(re) + ' - ' + FloatToStr(im);
end;

procedure TObjekt2.init2(data: array of const);
begin
  re := data[0].VExtended^;
  im := data[1].VExtended^;
  sig := Format('Die Zahlen: %.2f und %.2f', data);
end;

end.


Danke für das Programm. Das mit dem array of const habe ich noch nicht so ganz verstanden. Angenommen ich möchte an die Methode init2 ein Objekt vom Typ TObjekt2 übergeben, wie mache ich das?

Elrond.
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Do 01.01.09 23:08 
user profile iconElrond hat folgendes geschrieben Zum zitierten Posting springen:
Das mit dem array of const habe ich noch nicht so ganz verstanden.
Overrides mit "verschiedenen" Parametern sind auch alles andere als normal, das sieht stark nach einem Designfehler aus. Vielleicht finden wir ja ein besseres Design, wenn du ein reales Beispiel nennen kannst.

_________________
>λ=
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 01.01.09 23:24 
user profile iconElrond hat folgendes geschrieben Zum zitierten Posting springen:
Das mit dem array of const habe ich noch nicht so ganz verstanden.
rvelthuis.de/article...rticles-openarr.html
Das hilft vielleicht beim Verständnis.

user profile iconElrond hat folgendes geschrieben Zum zitierten Posting springen:
Angenommen ich möchte an die Methode init2 ein Objekt vom Typ TObjekt2 übergeben, wie mache ich das?
Du kannst ja die gemeinsame Elternklasse als Typ des Parameters nehmen, meinst du das?

Oder willst du wirklich konkret TObjekt2 immer übergeben? Das ginge via Forwarddeklaration:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
  TObjekt1 = class(TObject);
  TObjekt2 = Class(TObjekt1);

  TObjekt1 = class(TObject)
  public
    procedure init(a: TObjekt2); virtualabstract;
  end;

  TObjekt2 = Class(TObjekt1)
  public
    procedure init(a: TObjekt2); override;
  end;
Aber ich nehme an das meintest du nicht.

Ansonsten kann ich mich nur user profile iconKha anschließen:
Ohne zu wissen was du vor hast können wir dir kein besseres Design vorschlagen. Und du selbst scheinst ja nicht so genau zu wissen was eigentlich wie zusammenhängen soll. Bzw. das nicht mit Delphi in Einklang bringen zu können. ;-)
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 01.01.09 23:27 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconElrond hat folgendes geschrieben Zum zitierten Posting springen:
Das mit dem array of const habe ich noch nicht so ganz verstanden.
Overrides mit "verschiedenen" Parametern sind auch alles andere als normal, das sieht stark nach einem Designfehler aus. Vielleicht finden wir ja ein besseres Design, wenn du ein reales Beispiel nennen kannst.


Ok. Das Ziel hatte ich ja schon mal weiter oben skizziert. Angenommen, ich habe verschiedene Objektklassen TVektor, TKomplexezahl und so weiter. Alle diese Klassen haben Methoden mit unterschiedlichen Parametern aber identischen Namen. Zum Beispiel eine Methode Addiere.

Einmal addiere ich also zwei Vektoren, ein anderes mal zwei komplexe Zahlen. Ich möchte nun an einer zentralen Stelle (zum Beispiel hier: procedure TForm1.AdditionClick(Sender: TObject) eine Addition durchführen: p1.Addiere(p2).

Das soll für alle Typen von addierbaren Objekten gelten. D.h. einmal sind p1, p2 Instanzen der Klasse TVektor, ein andermal Instanzen der Klasse TKomplexeZahl. Was jeweils gilt, möchte ich während der Laufzeit festlegen. Das hatte ich mir so in der Art p1:=TVektor.Create oder p1:=TKomplexeZahl.Create vorgestellt.

Jetzt ergeben sich natürlich Probleme.

1) Von welchem Typ sollten die Variablen p1,p2 bei der Deklaration sein?

2) Was mache ich mit den unterschiedlichen Parametern?

Wenn ich später weitere addierbare Objekte hinzufügen möchte (zum Beispiel Brüche oder ganze Zahlen), müssten die zentralen Stellen des Programms nicht geändert werden, denn jeder neue Objekttyp bringt ja seine ganz eigenen Methoden zum Addieren mit, benötigt aber unterschiedliche Parameter, teilweise auch unterschiedliche Parameterzahlen (2 ganze Zahlen = 2 Parameter, zwei Brüche = 4 Parameter (zwei Zähler, zwei Nenner)). Leider ist das wohl doch nicht so einfach.

Ich bin dankbar für jede gute Idee.

Elrond.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 01.01.09 23:42 
Das wiederum ist ein relativ einfaches Problem. Du brauchst doch gar nicht verschieden viele Parameter. Schließlich wird dein Bruch z.B. doch in einem Objekt gekapselt. Und an die Methode übergibst du den Bruch als ganzes Objekt, als einen Parameter. ;-)

Die andere Möglichkeit wäre natürlich theoretisch die über ein Array als Parameter, sei es ein normales open array als Parameter oder ein variant open array parameter (array of const).
Das ist in diesem Fall aber keine gute Wahl, aus den von dir selbst genannten Gründen.

// EDIT:
Ach ja: neuere Versionen von Delphi (ab Delphi 2006) kennen auch Operator Overloading:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
  TBruch = record
    Zaehler, Nenner: Integer;
    class operator Add(a, b: TBruch): TBruch;
  end;
Dann kannst du einfach schreiben:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
var
  test1, test2: TBruch;
begin
  ...
  test1 := test1 + test2;
Mit Delphi für Win32 geht das nur mit Records, mit Delphi Prism unter .NET geht das auch mit Klassen.

Und mit C# geht das natürlich auch. ;-)

// EDIT2:
Du könntest den Record ja auch in eine Klasse als Eigenschaft einbetten, dann hättest du beides, wenn dir die Funktionalität eines Records nicht ausreicht.
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Fr 02.01.09 00:48 
Ja, hier bietet sich dann wirklich ein Interface an:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
type INumeric = interface
  function Add(aOther : INumeric) : INumeric;
  function Sub(aOther : INumeric) : INumeric;
  function Negate : INumeric;
  [...]

In den Implementationen musst du dann nur noch überprüfen, ob Self und der Parameter wirklich vom gleichen(/kompatiblen) Typ sind.
Man könnte auch mit einer Basisklasse ein wenig Arbeit abnehmen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
type NumericBase = class(TObject, INumeric)
  function Add(aOther : INumeric) : INumeric; virtualabstract;
  function Sub(aOther : INumeric) : INumeric; virtual;
  function Negate : INumeric; virtualabstract;
  [...]

function NumericBase.Sub(aOther : INumeric);
begin
  Result := Add(aOther.Negate);
end;

_________________
>λ=
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Fr 02.01.09 01:29 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Das wiederum ist ein relativ einfaches Problem. Du brauchst doch gar nicht verschieden viele Parameter. Schließlich wird dein Bruch z.B. doch in einem Objekt gekapselt. Und an die Methode übergibst du den Bruch als ganzes Objekt, als einen Parameter. ;-)


Bei Init habe ich sehr wohl verschiedene Parameterzahlen. Bei einem Objekt vom Typ ganze Zahl ist es ein Integer-Wert, bei einem Bruch sind es zwei Integer-Werte. Den Bruch kann ich nicht übergeben, denn dessen Werte sollen ja erst initialisiert werden.

Und auch das Kapseln führt zum Anfangsproblem zurück, denn einmal habe ich so etwas wie

procedure Add(s:TKomplex);

in der Klassendefinition und ein anderes mal

procedure Add(s:TVektor);

und wenn ich dann p1.Add(p2) schreibe dann schimpft der Compiler entweder, dass p2 nicht vom Typ TKomplex ist oder aber, dass p2 nicht vom Typ TVektor ist, je nachdem wie p2 definiert ist. Deswegen hatte ich mir ja überlegt, beide Klassen von einer gemeinsamen Basisklasse abzuleiten. Aber da wird dann jeweils die abstrakte Methode aufgerufen und ein Laufzeitfehler tritt auf.

Elrond
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 02.01.09 01:35 
user profile iconElrond hat folgendes geschrieben Zum zitierten Posting springen:
Bei Init habe ich sehr wohl verschiedene Parameterzahlen. Bei einem Objekt vom Typ ganze Zahl ist es ein Integer-Wert, bei einem Bruch sind es zwei Integer-Werte. Den Bruch kann ich nicht übergeben, denn dessen Werte sollen ja erst initialisiert werden.
Aber bei der Initialisierung ist doch keine allgemeingültige Lösung nötig. :gruebel:
Da musst du doch ohnehin das Objekt gezielt mit einem bestimmten Typ erstellen. Und dann kannst du es dabei auch direkt initialisieren. Immer wenn du die mit den Werten direkt arbeitest, kannst du doch ohnehin nicht mehr allgemein bleiben.

Und bei mir habe ich ja auch das Array benutzt, solche Konstruktionen wären theoretisch ja auch denkbar.

user profile iconElrond hat folgendes geschrieben Zum zitierten Posting springen:
Deswegen hatte ich mir ja überlegt, beide Klassen von einer gemeinsamen Basisklasse abzuleiten. Aber da wird dann jeweils die abstrakte Methode aufgerufen und ein Laufzeitfehler tritt auf.
Aber nur, wenn du nicht die Oberklasse als Parameter benutzt. Wie es richtig geht, habe ich doch in dem Beispiel gezeigt. Du hast immer einen Parameter vom Typ der Oberklasse als Parameter. Bzw. es wird eine solche Methode von allen implementiert.

Mit einem Interface geht das ja. Dann brauchst du nicht einmal von einer Oberklasse ableiten, wie ich es im Beispiel gemacht hatte.

Ich glaube ich muss einmal ein richtiges Beispiel machen, das scheint so nicht wirklich rüberzukommen wie das funktioniert. :nixweiss: