![]() |
Basisklasse und davon abgeleitet drei Standardklassen
Hallo zusammen,
irgendwie stehe ich gerade derbe auf dem Schlauch, und hoffe, mir kann just jemand auf die Sprünge helfen. Folgendes: Ich möchte eine Basisklasse TBasisklasse haben, welche ein paar Eigenschaften und ein paar Methoden hat. Nun möchte ich von dieser Basisklasse drei Kindklassen ableiten. Diese sollen einmal die Eigenschaften und Methoden von der Basisklasse erben, aber eigentlich wie ein TEdit, TLabel bzw. TMemo sein (nur als Beispiel). Also ungefähr so:
Delphi-Quellcode:
Wenn ich nun also ein Objekt aus der Klasse TEditklasse erzeuge, möchte ich im Prinzip ein TEdit haben, welches aber zusätzlich über die Eigenschaften aus TBasisklasse verfügt.
Type
TBasisklasse = Class private FEigenschaft1: Integer; FEigenschaft2: Integer; FEigenschaft3: Integer; FWind: String; Procedure SetWind(Const Value: Integer); public Property Wind: String read FWind write SetWind; End; TEditklasse = Class(TBasisklasse) End; TLabelklasse = class(TBasisklasse) end; TMemoklasse = Class(TBasisklasse) End; Der Grund: Wenn an 'SetWind' etwas geändert werden muss, muss dieses dann nur in der Basisklasse gemacht werden. Ich weiß, dass sich das ziemlich wirr anhört, aber ich hoffe, dass meine Intention jemand versteht. Ich weiss absolut nicht, wie ich das aufbauen soll :cry: |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Ich würde erstmal die Basisklasse von TObject ableiten.
Inwiefern meinst du, du willst ein TEdit, ein TLabel und ein TMemo von TBasisklasse ableiten? Welche Proceduren willst du denn übertragen? Ich sehe nirgends ein virtual / override. Eventuell wäre eine präzisere Formulierung deines Anliegens hilfreich ;) Zitat:
Zitat:
|
Re: Basisklasse und davon abgeleitet drei Standardklassen
Von TObject brauchst du nicht explizit ableiten, da das auf jeden Fall geschieht. Jede Klasse in Delphi erbt automatisch direkt oder indirekt von TObject.
|
Re: Basisklasse und davon abgeleitet drei Standardklassen
Das was Du benötigst ist ein Interface und eine zugehörige Delegatenklasse. Such mal in der OH nach 'Interface' und 'implements'. Das Interface schreibst du dann zusätzlich in die Klassendeklaration (=class(TBasisklasse,Interface)). In dem Interface implementierst Du dann die Methoden, die jetzt deine Basisklasse besitzt. Interfaces umgehen das Problem, dass in Delphi keine Mehrfachvererbung möglich ist.
|
Re: Basisklasse und davon abgeleitet drei Standardklassen
Zitat:
Zitat:
Also: Erzeuge ich mir ein Objekt von TEditklasse, dann möchte ich, dass auf meiner Form ein TEdit erscheint, welches aber zusätzlich die Eigenschaft 'Wind' aus der Basisklasse besitzt. Erzeuge ich mir ein Objekt von TLabelklasse, dann möchte ich, dass auf meiner Form ein TLabel erscheint, welches aber zusätzlich die Eigenschaft 'Wind' aus der Basisklasse besitzt. Erzeuge ich mir ein Objekt von TMemoklasse, dann möchte ich, dass auf meiner Form ein TMemo erscheint, welches aber zusätzlich die Eigenschaft 'Wind' aus der Basisklasse besitzt. Muss ich Änderungen an 'SetWind' vornehmen, so mache ich das nur in der Basisklasse - die Änderungen übertragen sich auf die drei Kindklassen. Dass das so, wie ich es oben dargestellt habe, nicht funktionieren kann, ist klar. Sollte das Ganze nur veranschaulichen. Werde mir das mit den Interfaces von Sidorion mal zu Gemüte führen. |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Das wird so nicht gehen. Und zwar weil du erweiterte Klassen von TEdit, TMemo und TLabel haben willst. Deine TBasisklasse kann aber nicht von allen 3 erben.
Es bleibt dir wohl nichts anderes übrig, als 3 neue Unterklassen von TEdit, TMemo und TLabel zu erstellen, und dort jeweils als Referenz auf deine TBasisklasse zu referieren (Assoziation im UML Jargon) |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Zitat:
|
Re: Basisklasse und davon abgeleitet drei Standardklassen
Zu meiner Schande habe ich in Delphi noch nie mit Interfaces gearbeitet, aber wenn die so funktionieren wie in .NET, dann hilft das nicht.
In dem Fall wäre ein interface nur eine Erweiterung der Klasse die sagt: "Diese Klasse hier hat diese Properties und diese Methoden.". Die Implementierung des Interfaces - im konkreten Fall die SetWind Methode und das Property Wind - müssen jedoch auf jeder Klasse die das Interface verwendet selber implementiert werden. |
Re: Basisklasse und davon abgeleitet drei Standardklassen
In Interfaces kannst du nur Methoden und Propertys, aber keine Felder definieren, außerdem keine Implentierung, also nur abstrakt. Und dann müsstest du in jeder Klasse den Code für SetWind einfügen.
Das sind solche Fälle, in denen man sich echte Mehrfachvererbung wie in C++ wünscht. |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Hmm,
Interface scheint tatsächlich nicht das Richtige zu sein. Dort habe ich ja keine Möglichkeit Felder zu deklarieren. Edit: Wie Apollonius sagt :wink: Aber nochmal: Mehrfachvererbung würde ja bedeuten, dass meine TBasisklasse von den drei Standardklassen erben würde. Ich möchte es aber ja genau andersrum: Die drei Standardklassen sollen ja die Felder und Methoden der Basisklasse erben. |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Mehrfachvererbung bringt mehr Probleme als Vorteile, deshalb findet man sie nicht in neuren Sprachen wie Java, Delphi, C#, ..., wo man Vererbung per Interfaces präferiert.
|
Re: Basisklasse und davon abgeleitet drei Standardklassen
Zitat:
TEdit wird nicht von Basisklasse abgeleitet. Ich möchte eine Klasse, deren Instanz der eines TEdit entspricht, zusätzlich aber die Eigenschaften aus TBasisklasse übernimmt. Und wie ich schon schrieb: so, wie ich das im Delphi-Code meines ersten Beitrages dargestellt habe, kann das nicht funktionieren; das weiß ich. Aber genau dort liegt ja mein Problem - ich weiß nicht, wie ich dieses Konstrukt erzeugen soll. Edit: was ich nicht möchte, ist soetwas:
Delphi-Quellcode:
Type
TEditklasse = Class(TEdit) private FEigenschaft1: Integer; FEigenschaft2: Integer; FEigenschaft3: Integer; FWind: String; Procedure SetWind(Const Value: Integer); public Property Wind: String read FWind write SetWind; End; TLabelklasse = class(TLabel) private FEigenschaft1: Integer; FEigenschaft2: Integer; FEigenschaft3: Integer; FWind: String; Procedure SetWind(Const Value: Integer); public Property Wind: String read FWind write SetWind; end; TMemoklasse = Class(TMemo) private FEigenschaft1: Integer; FEigenschaft2: Integer; FEigenschaft3: Integer; FWind: String; Procedure SetWind(Const Value: Integer); public Property Wind: String read FWind write SetWind; End; |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Mehrfachvererbung wäre hier sehr praktisch. Du könntest einfach schreiben
Delphi-Quellcode:
und fertig wärst du. Ich habe mir auch schon eine weniger eingeschränkte Form der Mehrfachvererbung gewünscht, als es sie in Delphi gibt. Das
TEditklasse=class(TEdit, TBasisklasse)
![]() |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Zitat:
Wenn doch so viele Leute eine solche Funktionalität gerne hätten - gibt es dann keinen 'Workaround'? Interfaces sind es ja aufgrund der nicht vorhandenen Möglichkeit, Felder etc. zu deklarieren, nicht. Und nein - für mich ist kein Workaround, das Ganze in C-basierten Sprachen zu realisieren :wink: Abgesehen davon, dass ich kein C[x] beherrsche, sind mir meine Arbeitsmittel vorgegeben. |
Re: Basisklasse und davon abgeleitet drei Standardklassen
An Workarounds mangelt es nicht, dafür müsste man aber erst etwas mehr von den Hintergründen erfahren; man möchte schließlich das freakigstmögliche Design-Pattern einsetzen ;) . Z.B. könnte es sinnvoll sein, das ganze als Factory-Interface zu gestalten:
Delphi-Quellcode:
Oder auch einfach als
type
IMyFactory = interface function CreateSomething : TBasisklasse; end; [...] function TMyEdit.CreateSomething; begin Result := TEditklasse.Create; end;
Delphi-Quellcode:
(Alle Angaben ohne Gewähr, hab Interfaces in Delphi nur ein-, zweimal benutzt)
type
IMyExtender = interface function GetSomething : TBasisklasse; property Something : TBasisklasse read GetSomething; end; |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Zitat:
Naja, zu den Hintergründen - den Sinn habe ich ja bereits erläutert, und ich sehe ein, dass Mehrfachvererbung eine nette Sache wäre. Ich habe es jetzt so gelöst, dass ich einfach in der Basisklasse ein Feld 'FControl' und eine entsprechende Property dazu erstellt habe, dem ich dann im Constructor, den ich in den Kindklassen überschreibe, einfach eine Instanz der entsprechenden Klasse zuweise, und erst danach den Constructor der Basisklasse aufrufe. Dann spreche ich das Ganze halt hinterher nicht nur mit dem Instanzennamen an, sondern mit Instanzenname.Control Mit Mehrfachvererbung hätte mir zwar besser gefallen, aber so gehts auch.
Delphi-Quellcode:
Edit: freue mich natürlich noch immer über anderweitige Lösungsmöglichkeiten, wenn Ihr welche habt :stupid:
TBasisklasse = Class
private FControl: TControl; FEigenschaft1: Integer; FEigenschaft2: Integer; FWind: Integer; Procedure SetWind(Const Value: Integer); public Constructor Create(AOwner: TComponent); virtual; Property Control: TControl read FControl; Property Wind: Integer read FWind write SetWind; End; TEditklasse = Class(TBasisklasse) public Constructor Create(AOwner: TComponent); override; End; TLabelklasse = Class(TBasisklasse) Constructor Create(AOwner: TComponent); override; End; TMemoklasse = Class(TBasisklasse) Constructor Create(AOwner: TComponent); override; End; [...] Constructor TBasisklasse.Create(AOwner: TComponent); Begin FEigenschaft1: FControl.Width; FEigenschaft2: FControl.Height; End; Procedure TBasisklasse.SetWind(Const Value: Integer); Begin FWind := Value; FControl.Width := FEigenschaft1 * Value; FControl.Height := FEigenschaft2 * Value; End; Constructor TEditklasse.Create(AOwner: TComponent); Begin FControl := TEdit.Create(AOwner); Inherited; End; Constructor TLabelklasse.Create(AOwner: TComponent); Begin FControl := TLabel.Create(AOwner); Inherited; End; Constructor TMemoklasse.Create(AOwner: TComponent); Begin FControl := TMemo.Create(AOwner); Inherited; End; |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Hier steht nicht viel brauchbares ! Das einzige wäre ein Tedit und ein TMemo. Die besitzen zumindest mal Editier-Funktionalitäten. Ein TLabel hat nicht mal die. Wozu soll dieser unzusammenhängende Kram jetzt zusammengeschmissen werden ? Wird ein spezielles TEdit gebraucht, dann leite das von TEdit ab usw. Die Funktionalität bei TObject (= bei Null) etc. angefangen selber einzubauen ist völliger Blödsinn. :mrgreen:
|
Re: Basisklasse und davon abgeleitet drei Standardklassen
Wenn ich mich jetzt nicht vollkommen vertue, könnten
![]() |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Hallo,
wenn ich mich recht erinnere gibt es für Delphi mittlerweile ClassHelper. Mal hier im Forum suchen. Wenn man keine property sondern nur eine Setter und Getter Methode für WInd verwendet könnte man einen Classhelper verwenden. |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Ich habe auch schon daran gedacht, aber Helferklassen können keine Felder enthalten.
|
Re: Basisklasse und davon abgeleitet drei Standardklassen
Zitat:
Zitat:
:!: Vielleicht ein kurzer Satz zur Erläuterung. Seitens meines Arbeitgebers bin ich sehr eingeschränkt, was die Herausgabe von Informationen betrifft. Ich darf mich zwar hier im Forum aufhalten, darf auch Fragen stellen und Antworten geben - ich darf allerdings keinerlei Originalquellcode - und seien es nur Variablennamen - veröffentlichen, der in irgendeinem Zusammenhang mit unserem Projekt steht; dafür musste ich sogar unterschreiben. Über Sinn und Unsinn dieser Richtlinie kann man streiten - möchte ich aber nicht, da ich - und auch niemand anderes - etwas daran ändern kann. Aus diesem Grund muss ich alles, was ich hier reinposte, irgendwie abstrahieren - dabei kommt dann gelegentlich auch etwas zusammenhangloses Zeugs heraus. Daher habe ich - so dachte ich zumindest - eindeutig geschildert, was ich haben möchte. Da das anscheinend nicht der Fall ist, versuche ich es nocheinmal. Ich muss dynamisch verschiedene Controls erzeugen. Nehmen wir beispielsweise(!) TEdit, TCheckbox und TComboBox. Alle diese drei Controls müssen mit einer zusätzlichen Funktionalität ausgestattet werden. Nennen wir diese Funktionalität 'Sag mir Deinen Startwert' (nur als Beispiel!). So, alle diese Controls werden mit einem Startwert (Text, Checked, Text) belegt. Dieser kann zur Laufzeit geändert werden. Irgendwann sollen mir diese Controls auf Zuruf ihren Startwert mitteilen. Ich erzeuge mir also für alle 3 Controls eine eigene Klasse. Diese Klasse bekommt ein Feld FStartwert. In diesem wird der Initialwert gespeichert, sobald das Objekt erzeugt worden ist. Jetzt gibt es zusätzlich die Public-Funktion 'GibStartwert'. Diese malt dem Startwert (FStartwert) ein paar Blümchen aufs Hemd und gibt ihn in einer Message aus. Fertig. So, jetzt kann ich allen diesen 3 abgeleiteten Klassen (TMeinEdit, TMeineCheckbox und TMeine ComboBox) das Feld FStartwert und die Methode GibStartwert geben. Bei allen sähe die Methode GibStartwert gleich aus. Müsste ich nun an dieser Methode etwas ändern, so müsste ich das in allen drei Klassen tun. Und das ist der Knackpunkt, wo ich denke, dass das aus Sicht der OOP nicht so günstig ist. Also dachte ich mir - erzeuge ich mir eine Basisklasse, die das Feld FStartwert und die Methode GibStartwert hat, und leite dann meine 3 Controls davon ab - naja, den Rest kennt ihr ja. Ich hoffe, dass mein Vorhaben - auch wenn es wieder abstrahiert ist - etwas deutlicher wurde. |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Delphi-Quellcode:
Ich weiß nicht, ob es direkt kopiert so funktioniert (hab kein Delphi, es zu testen), aber im Prinzip dürfte das doch deinen Anforderungen entsprechen..?
type
IStartwert = interface function GibStartwert: string; end; TStartwert = class(TInterfacedObject, IStartwert) private fStartwert: string; public function GibStartwert: string; constructor Create(startwert: string); end; TEditEx = class(TEdit, IStartwert) private fStartwert: TStartwert; public property Startwert: IStartwert read fStartwert implements IStartwert; constructor Create; end; function TStartwert.GibStartwert: string; begin Result := fStartwert; end; constructor TStartwert.Create(startwert: string); begin inherited Create; fStartwert := startwert; end; constructor TEditEx.Create; begin inherited Create; fStartwert := TStartwert.Create('blubb'); end; |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Zitat:
|
Re: Basisklasse und davon abgeleitet drei Standardklassen
@Dax:
Prinzipiell ist erfüllt es seinen Dienst, ja. Aber: da hat dann ja jede Klasse ein Feld und eine zusätzliche Property die ich explizit in der Klasse angeben muss. Ich weiss, dass ist - ähm - Kleinscheisserei, aber wenn es nur so geht - dann geht es halt nur so - danke :zwinker: Zu den Helferklassen komm eich gleich. @Hansa: Ja, eine zusätzliche Property - das war ja halt die Frage, ob OOP nicht minimalistisch arbeitet; aber anscheinend ja nicht. Den Ober-Häuptlingen kann man leider nicht reinreden. @Apollonius, Jens Schumann und Dax: Helferklassen helfen hier tatsächlich. Und es können sogar Klassenfelder erzeugt werden :-D Das Ganze sieht dann so aus (wieder abstrahiert):
Delphi-Quellcode:
TMyEdit = Class(TEdit)
public Constructor Create(AOwner: TComponent); override; End; TMyClassHelper = Class helper For TMyEdit Class Var FStartwert: String; Procedure GibStartwert(_sPrefix: String); End; |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Hallo,
Zitat:
Gruß Hawkeye |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Guten Morgen.
Zitat:
Nach langem hin und her habe ich mich letztendlich doch dazu entschlossen, von den benötigten Standardklassen abzuleiten, und dort die jeweilige Funktionalität direkt einzubauen. Nichts desto trotz war dieser Thread wiedermal eine Erfahrung und ich habe etwas dazu gelernt: Interfaces und Helferklassen - danke an alle, die mir in diesem Thread geantwortet haben :!: Und nebenbei werde ich mich dann noch mal dem Thema 'Assoziation' widmen - danke hier an Jelly :wink: |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Na da hört mal wieder keiner zu :zwinker: . Dein Problem löst sich wie folgt:
Delphi-Quellcode:
TMyIntfHelper ist ein Delegat, der alle Methoden von IMyInterface implementiert. Dieser muss nun in jeder Klasse, die IMyInterface deklariert instanziert werden und erledigt dort die Drecksarbeit. Jetzt kannst Du problemlos das von TEdit geerbte TMyEdit als IMyInterface ansprechen und die Methoden benutzen. Das selbe würde dann für alle anderen Klassen mit dem Interface gelten.
Type
// Interface, das kriegen alle drei Klassen IMyInterface=interface(IInterface) //hier kommt dann ne GUID, die wird automatisch erzeugt procedure MyWind; end; //Helperklasse für das Interface. Diese weiss, was zu tun ist, wenn die Methoden gerufen werden TMyIntfHelper=Class(TObject) FMemberusw: Typ; public procedure MyWnd; end; // ein Beispiel TMyEdit=Class(TEdit,IMyInterface) private FHelper: TMyIntfHelper; ... public property MyHelper: TMyIntfHelper Read FHelper implements IMyInterface; end; // mehr ist in TMyEdit im prinzip nicht zu schreiben, damit das Interface implementiert wird Der Schlüssel liegt sozusagen in der Direktive Implements. Die sorgt dafür, dass die angegebene Property für die Bearbeitung des Interfaces sorgt. Die Klasse selber muss sich darum nichtmehr kümmern. Dieses Konstrukt ist wesentlich eleganter, als Mehrfachvererbung, da hier das Diamantproblem garnicht entstehen kann, jedoch alle Möglichkeiten gegeben sind. Nachtrag: Jetzt kannst Du einfach TMyEdit.MyWind rufen, alsob das Interface direkt in TMyEdit implementiert wäre. |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Zitat:
Wahrscheinlich war das auch genau die 'eine Property', die Hansa meinte. Ich werde mir das Ganze mal verinnerlichen - vielen Dank :-D Edit: Eine Frage habe ich dennoch: Wie kann ich denn jetzt in TMyIntfHelper.MyWind auf Eigenschaften des späteren Edits zugreifen? Ich habe also in TMyIntfHelper einige Felder. Diese muss ich der Methode MyWind den Eigenschaften des späteren Edits zuweisen, bspw so:
Delphi-Quellcode:
MeinSpäteresEdit kennt er ja nicht. Gibt es da irgendwie eine Art Platzhalter?
TMyIntfHelper=Class(TObject)
FEinString: String; public procedure MyWind; end; Procedure TMyIntfHelper.MyWind begin MeinSpäteresEdit.Text := FEinString; end; |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Na du könntest beispielsweise den Helper von TControl ableiten. Dann wird in den Owner (THelper.Create(Self)) das Objekt geschrieben und du kannst dann im Helper über den Owner und RTTI (Unit Typinfo) zugreifen. Du kannst auch einen Event im Helper deklarieren, im Konstruktor Methodenzeiger übergeben usw.
Dir stehen hier sämtliche Objektkommunikationsmöglichkeiten offen. |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Zitat:
Das ist eine interessante Sache, mit dem "implements". Das kannte ich noch nicht. Werd mir das heut abend aber auch mal reinziehen. |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Besonders interessant ist, dass Interface- und Klassen-Propertys ganz unterschiedlich gehandhabt werden. Bei Interface-Propertys z.B. erhält die eigentliche Kasse gar keine eigene Interface-VMT, bei Klassen-Propertys schon.
|
Re: Basisklasse und davon abgeleitet drei Standardklassen
@jelly: natürlich musst Du die Methode bei einer Instanz rufen. Ich hab das T nur hingeschrieben, um zu zeigen, dass kein Cast oder Umweg über die implementierende Property notwendig ist.
Allerdings geht das nur, wenn Du eine Variable vom Typ TMyEdit hast. Ist die Variable vom Typ TEdit oder weiterer Vorgänger, musst Du erst auf das Interface casten (mit As) oder auf eine Variable vom Typ des Interfaces zuweisen (Achtung hier kommt es zu Ausnahmen wenn wirklich eine Instanz von TEdit angelegt wurde). Ach ja: Interfaces bringen eine Referenzzählung mit (das macht schon IInterface bzw. TInterfacedObject). Willst Du diese Klassen dann benutzen, musst Du sie in eine Variable des Interfacetyps instanzieren oder in der Helperklasse die Referenzzählung unterdrücken. Steht auch irgendwo in der OH. Ansonsten wird die Inszanz gleich nach dem Konstruktoraufruf wieder weggeschmissen. Beispiel:
Delphi-Quellcode:
Var
iMyEdit: IMyInterface; Begin iMyEdit:=TMyEdit.Create(..); End; |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Zitat:
Bye Christian |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Is ja süß, man muss immer den Umweg über eine Interface-Variable gehen..
|
Re: Basisklasse und davon abgeleitet drei Standardklassen
Nein. Es reicht ein Cast. (MyObj As IMyInterface).MyWnd.
Wie gesagt, wenn man mit Interfaces arbeitet sollte man sowieso Interfacevariablen nutzen. Ist sozusagen eine weitere Abstraktionsstufe. Bei Objektorientierung habe ich einen schwarzen Kasten (einer bestimmten Art), an dessen Henkeln ich runschraube. Mit Interfaces Interessiert mich nichtmal mehr der Kasten, sondern nur noch, dass er bestimmte Henkel hat, an denen ich rumschrauben kann. Ein Interface ist jedenfalls das einzige Sprachkonstrukt in Delphi mit dem sowas geht. Mehrfachvererbung iss ja nicht. |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Zitat:
|
Re: Basisklasse und davon abgeleitet drei Standardklassen
Zitat:
Warum müssen die zusätzlichen Properties so eng mit den Controls verkoppelt werden ? Es gibt ja auch das ![]() Angenommen dein Modell wäre eine elektronische Schaltung mit vielen Bauteilen. Jedes Bauteil hat unterschiedliche Properties (Widerstand, Kapazität,...). Der View muss dynamisch zur Laufzeit aufgebaut und mit Controls versehen werden. Anstatt nun die Controls mit zusätzlichen Properties auszustatten, könnte man doch eher den View als Objektmodell (TResistor, TWire, TDiode, ...) aufbauen und dort alle Properties unterbringen. Im View gibt es nun eine Liste, in der vermerkt ist, welches Control an welches Bauteil angekoppelt ist. ==> alle Controls bleiben Standard sind aber an das Modell gekoppelt |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Also, ich habe nun mal eine Beispielanwendung, basierend auf Sidorions Posts geschrieben. Habe mir dieses Mal auch ein etwas sinnvollerers Beispiel überlegt, damit das Ganze etwas anschaulicher wird. Standardcontrols (Label, Edit etc.) sollen eine Zoommöglichkeit bekommen (das ist wieder nur ein Beispiel - bitte keine anderen Wege aufzeigen, wie man die Dinger zoomen kann - es geht mir jetzt um das Prinzip mit den Interfaces :wink: ) Beim Erzeugen der Mainform werden ein Label und ein Edit erzeugt (liegen beide übereinander, ist aber jetzt auch egal). Mittels des SpinEdits sollen die beiden vergrößert bzw. verkleinert werden. Die Probleme: Bei Betätigung des SpinEdits gibt es eine Zugriffsverletzung in der Zoom-Methode. Die Create-Methode der TBasisklasse (des Helfers) wird nicht aufgerufen - hätte erwartet, dass diese beim Erzeugen der Controls aufgerufen wird. Da habe ich halt das beschriebene Verständnisproblem mit der Kommunikation zwischen Objekt, Interface und Helferklasse. Hoffe, mir kann jemand weiterhelfen. Und bitte dran denken - es geht mir jetzt nur um das Prinzip mit diesen Interfaces. Ob diese Art zu zoomen schön ist, oder nicht, ist in diesem Falle vollkommen egal. Das soll nur dem besseren Verständnis meines Anliegens diesen - danke. |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Wie kommt denn die TBasisklasse in den FHelper? Du kannst nur mit Interfaces arbeiten, die nicht nil sind. Folglich muss der Konstruktor von TEditklasse und TLabelklasse überschrieben werden.
Zur Sache mit dem Cast: Da habe ich auch schon mal dran gehangen. Der Trick ist, dass der internen Cast-Funktion eine GUID übergeben werden muss. Verpasse ITestInterface also eine GUID. Bei Interfaces musst du übrigens zwingend mit dem as-Cast arbeiten, der function-syle-Cast führt fast zwingend zur Zugriffsverletzung, da in der falschen VMT die Funktion gesucht wird (ich will jetzt nicht mit den Interna langweilen, aber wer will, kann ja mal schauen, wie Interface-Methoden eigentlich aufgerufen werden). |
Re: Basisklasse und davon abgeleitet drei Standardklassen
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Habe nun das Create der Objekte überschrieben und weise darin FHelper eine Instanz der Basisklasse zu - so:
Delphi-Quellcode:
Constructor TLabelklasse.Create(AOwner: TComponent);
Begin Inherited; FHelper := TBasisklasse.Create(self); End; Zitat:
Nun kann ich so casten:
Delphi-Quellcode:
Nun ja, ich habe wie gesagt, die Create-Methode überschrieben und das casten angepasst.
(oEdit As ITestInterface).Zoom(SpinEdit1.Value);
Ich bekomme nun zumindest schonmal keine Zugriffsverletzung mehr - das gewünschte Zoomen funktioniert aber trotzdem noch nicht - genauer gesagt passiert gar nichts, wenn ich den SpinEdit ändere. Naja, mal sehen, wo 's hängt. Danke erstmal, dass ich soweit gekommen bin ;) Edit: das Zoomen funktioniert nicht, da die Initialwerte im Create der Basisklasse alle als 0 ankommen. Ich dreh hier nochmal am Reifen.... :wall: Edit: Habe mal eine aktualisierte Version hochgeladen Sorry, aber bei mir hat's schon immer etwas länger gedauert, bis es 'klick' gemacht hat :? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:05 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz