"Alternative" Vererbung

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Jo@Win
Beiträge: 18
Registriert: Do 3. Jan 2013, 14:57

"Alternative" Vererbung

Beitrag von Jo@Win »

Folgendes Problem, hier etwas vereinfacht:
Ich möchte je nach Konfiguration eine Klasse C von Klasse A oder Klasse B vererben.
Klasse A und B implementieren bestimmte Methoden (hier Test0) komplett unterschiedlich, aber Klasse C macht immer das gleiche.
Ich kann auch nicht Klasse C als gemeinsamen Vorfahren implementieren, da C in der Kette ganz unten sein muss.
Bisher ging das mit einem Kompilerschalter, der je nach Konfiguration unterschiedliche Klassen erzeugte.
In Zukunft sollen aber beides zur Laufzeit alternativ möglich sein, deshalb brauche ich eine andere Lösung.
Möglich wäre das über includes, das ist aber nicht sehr übersichtlich und wenig elegant. 8)

Code: Alles auswählen

 
  TTest=class
    procedure Test0; virtual;abstract;
  end;
 
  TTestimp=class(TTest)
    procedure Test0; override;
  end;
 
  TTestimp1=class(TTestimp)
    procedure Test0; override;
  end;
 
...
 
  TTesta=class(TTestimp)
    procedure Test0; override;
  end;
 
  TTest_b=class(TTestimp1)  
    procedure Test0; override;
  end;
 
  { TTest_c }
  {$IFDEF a}
    TTest_c=class(TTesta)
  {$ENDIF }
  {$IFDEF b}
    TTest_c=class(TTestb)
  {$ENDIF }
    procedure Test0; override;
  end;
 
 
Schön wäre etwa so etwas in diese Richtung:

Code: Alles auswählen

TTest_c=class <TTest>
    procedure Test0; override;
  end;
 
var
  aTestclass:TTest;
 
begin
  if a then
    aTestclass := TTest_c<TTesta>.create
  else
    aTestclass := TTest_c<TTestb>.create;
 
end;

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: "Alternative" Vererbung

Beitrag von Socke »

Jo@Win hat geschrieben:Bisher ging das mit einem Kompilerschalter, der je nach Konfiguration unterschiedliche Klassen erzeugte.
In Zukunft sollen aber beides zur Laufzeit alternativ möglich sein, deshalb brauche ich eine andere Lösung.
Möglich wäre das über includes, das ist aber nicht sehr übersichtlich und wenig elegant. 8)
Schau dir die Datenbank-Units an (beispielsweise sqlite3 und sqlite3dyn). Jede Unit definiert einen Compiler-Schalter, greift aber über einen Include auf den selben Quelltext zu.

In deinen Programmen musst du dann natürlich darauf achten, welche Klasse du verwendest (unit1.TTest_c oder unit2.TTest_c).
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Jo@Win
Beiträge: 18
Registriert: Do 3. Jan 2013, 14:57

Re: "Alternative" Vererbung

Beitrag von Jo@Win »

Bespreche ich mal mit meinem Kollegen und probier es aus.
Wäre zwar auch nur eine Umgehung, aber besser als das, was ich mir ausgedacht habe. :D

Soner
Beiträge: 726
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: "Alternative" Vererbung

Beitrag von Soner »

Es gibt einen einfacheren Weg:
1. ) Mit eine Variable in der Klasse kontrollieren was aufgerufen werden soll, z.B.:

Code: Alles auswählen

 
procedure Testa.Test0;
begin
  if a then (self as TTestim).Test0
 else (self as TTestim1).Test0
end;
 
Wenn du if-Abfrage vermeiden willst machst du die Funktion als Zeiger (wie bei Ereignismethoden) und setzt sie am Anfang an richtige Funktion.

Jo@Win
Beiträge: 18
Registriert: Do 3. Jan 2013, 14:57

Re: "Alternative" Vererbung

Beitrag von Jo@Win »

@ Soner
Nein, das geht nicht, denn TTestA und TTestB machen was komplett anderes in den Methoden und rufen eventuell inherited auf.
Und es ist hier auch nur ein sehr vereinfachtes Beispiel. Die Klassen sind über mehrere Units verteilt, mit jeweils mehreren 1000 Codezeilen und kennen sich untereinander nicht.
Das eigentliche Problem ist TTestC. Das soll alternativ von A oder B erben.
Im restlichen Programm werden nur die Methoden aufgerufen, die TTest zur Verfügung stellt, welcher Nachkomme initialisiert wurde ist da unbekannt.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2809
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: "Alternative" Vererbung

Beitrag von m.fuchs »

Schildere doch mal dein eigentliches Problem, vielleicht gibt es eine andere Lösung.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Jo@Win
Beiträge: 18
Registriert: Do 3. Jan 2013, 14:57

Re: "Alternative" Vererbung

Beitrag von Jo@Win »

@ m.fuchs
Bei dem eigentlichen Problem ist Hardware mit im Spiel, die unterschiedlich angesteuert wird.
Die Klasse C ist eigentlich C1 und C2 die aber identischen Code besitzen, nur von unterschiedlichen Vorfahren erben. Siehe Beispielcode bei meiner Frage.
C steuert eine weitere Hardware, die A oder B benutzt, jedoch etwas anders als A und B. A und B werden können aber auch als jeweils eigenständige
Objekte (nicht als nur als Vorfahren von C) je nach Konfiguration benutzt werden.
Man könnte irgendwie die Objekte so umbauen, das C irgendwo in die Vorfahren eingebaut wird, das wäre aber auch aufwändig, unübersichtlich und fehlerträchtig.

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: "Alternative" Vererbung

Beitrag von Socke »

Jo@Win hat geschrieben:C steuert eine weitere Hardware, die A oder B benutzt, jedoch etwas anders als A und B. A und B werden können aber auch als jeweils eigenständige Objekte (nicht als nur als Vorfahren von C) je nach Konfiguration benutzt werden.
In diesem Fall ist Vererbung nicht geeignet. Besser geeignet ist die Assoziation, d.h. C hat eine Eigenschaft, die mit einem Objekt der Elternklasse befüllt wird. (habe ich so z.B. in https://github.com/SAmeis/pascalio umgesetzt, um GPIO-Leitungen des Prozessor genau so ansprechen zu können wie GPIO-Leitungen eines Externen ICs).

Ein ganz anderer Ansatz wäre RTTI zu nutzen und komplett dynamisch zu programmieren.
Das erhöht zwar die Komplexität, kann dann aber alles aufrufen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2809
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: "Alternative" Vererbung

Beitrag von m.fuchs »

Ich glaube aus dem was du schriebst herauszulesen, dass dir ein Decorator-Ansatz helfen könnte. Das ist eine ALternative zur Vererbung die flexibler ist und wahrscheinlich das macht, was du haben willst.

Ich hatte das mal als Vortrag vorgestellt, hier zu finden: http://www.lazarusforum.de/viewtopic.php?p=78582#p78582
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Antworten