[gelöst] Polymorphie macht mich wahnsinnig

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Marsmännchen
Beiträge: 294
Registriert: So 4. Mai 2014, 21:32
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10
CPU-Target: 64bit
Wohnort: Oranienburg

[gelöst] Polymorphie macht mich wahnsinnig

Beitrag von Marsmännchen »

Hi,

ich muss euch nochmal um Beistand bitten. Ich habe folgendes vor: Ich habe drei Klassen, die ein Spiel realisieren. Diese Klassen sollen möglichst lose gekoppelt sein, daher kommunizieren sie über das Beobachterpattern miteinander (FPOObserver und TPersistent... da hattet ihr mir in einem anderen Thread schon viel geholfen). Natürlich muss ich die Observer über die erfolgten Zustandsänderungen informieren. Dazu habe ich mir Datenklassen gebaut, die folgendermaßen definiert sind:

Code: Alles auswählen

(* Events *)
 
 { TMinedOutEvent }
 
 TMinedOutEvent = class     // parent class
   EventType : TMinedOutEventType;
 end;
 PMinedOutEvent = ^TMinedOutEvent;
 
 { TPlayerMovedEvent }
 
 TPlayerMovedEvent = class(TMinedOutEvent)
   NewPosition : TPos;
   function GetData : TPos;
 end;
 
 { TMinesNumberChangedEvent }
 
 TMinesNumberChangedEvent = class(TMinedOutEvent)
   NumberOfMines : Integer;
   function GetData : Integer;
 end;          // ... es gibt noch weitere Events...   


Das Feuern eines solchen Events funktioniert wie folgt:

Code: Alles auswählen

(* inform the Observers about movement *)
      FPlayerMovedEvent := TPlayerMovedEvent.Create;
      FPlayerMovedEvent.EventType:= moePlayerMoved;
      FPlayerMovedEvent.NewPosition := FPlayerPosition;
      FPONotifyObservers(self, ooCustom, @FPlayerMovedEvent);       


Das Abfangen eines solchen Events habe ich mir wie folgt vorgestellt (ist jetzt ein anderes Event, aber so soll es eigentlich überall funktionieren):

Code: Alles auswählen

procedure TPitch.FPOObservedChanged(ASender: TObject;
  Operation: TFPObservedOperation; Data: Pointer);
var
  PEvent : PMinedOutEvent absolute Data;
  Event : TMinedOutEvent;
  begin
  if Operation = ooCustom then
    begin
      if PEvent^.EventType = moeUserActionRequested then
      begin
        Event := PEvent^ as TUserActionRequestedEvent;
        MovePlayer(Event.GetData);
      end;
      if PEvent^.EventType = moeLevelChanged then
      begin
        Event := PEvent^ as TLevelChangedEvent;
        MakeNewLevel(Event.GetData);
      end;
    end;
end;           


Nur leider hustet mich der Compiler an:
minedoutpitch.pas(315,26) Error: identifier idents no member "GetData"


Also mein Problem:
Meine Events leiten alle von einer Basisklasse ab. Sie haben aber unterschiedliche Parameter in den Daten, die sie zurückgeben sollen (mal Integer, mal ein selbstdefiniertes Record usw.). Ich dachte, ich übergebe die Basisklasse. Diese enthält einen Hinweis darauf, was für ein konkretes Event eigentlich gemeint ist und in das caste ich dann. Nur... das mag der Compiler nicht. Wie kann ich sowas realisieren?
Zuletzt geändert von Marsmännchen am Di 11. Okt 2016, 18:12, insgesamt 1-mal geändert.
Ich mag Pascal...

df.id
Beiträge: 20
Registriert: Fr 23. Mai 2008, 00:29
OS, Lazarus, FPC: Windows|Linux (L 2.0.6 FPC 3.0.4)
CPU-Target: Intel
Wohnort: Münster
Kontaktdaten:

Re: Polymorphie macht mich wahnsinnig

Beitrag von df.id »

Event kennt nur Eigenschaften und Methoden von TMinedOutEvent. Egal, welches vererbte Klasse der Variable zugewiesen wird.

Einfache Lösung ohne die Variable Event:

Code: Alles auswählen

if PEvent^.EventType = moeUserActionRequested then
 MovePlayer((PEvent^ as TUserActionRequestedEvent).GetData);
if PEvent^.EventType = moeLevelChanged then
 MakeNewLevel((PEvent^ as TLevelChangedEvent).GetData);
 

Marsmännchen
Beiträge: 294
Registriert: So 4. Mai 2014, 21:32
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10
CPU-Target: 64bit
Wohnort: Oranienburg

Re: Polymorphie macht mich wahnsinnig

Beitrag von Marsmännchen »

Oh Mann, klar! Ich muss den Pointer casten, nicht irgendwas anders :shock: . Hatte ich wohl dezentes Brett vor dem Kopf. Danke!
(Die Eventvariable war schon ein verzweifelter Versuch, an GetData() ranzukommen).
Ich mag Pascal...

Antworten