Autor Beitrag
delphijanka
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 151

WinXP
D 2009 Arc., Java, C
BeitragVerfasst: Fr 17.09.10 16:13 
Hallo. Habe ein Problem. Gegeben:

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:
//Interfaces

type
  ILaufer = Interface
    procedure laufe;
  end;

type
  ISpringer = Interface
    procedure springe;
  end;

//Klassen

type
  TTier = class(TInterfacedObject)
    procedure esse;
  end;

type
  TElefant = class(TTier , ILaufer)
    procedure laufe;
  end;

type
  TKenguru = class(TTier, TSpringer)
    procedure springe;
  end;

type
  TLeopard = class(TTier, TLaufer, TSpringer)
    procedure laufe;
    procedure springe;
  end;


So verwalte ich meine Tiere:

ausblenden Delphi-Quelltext
1:
2:
var
  Tiere = array of TTier;


Nun möchte ich die Fähigkeiten der Tiere ausnutzen, was in Pseudo so aussieht:

wenn Tier[i] ist ein ISpringer
dann (Tier[i] als ISpringer).springe;


Ich weiß allerdings nicht, wie es geht. Kann mir einer helfen? Danke.

Moderiert von user profile iconNarses: Code- durch Delphi-Tags ersetzt
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Fr 17.09.10 16:40 
user profile icondelphijanka hat folgendes geschrieben Zum zitierten Posting springen:

Nun möchte ich die Fähigkeiten der Tiere ausnutzen, was in Pseudo so aussieht:

wenn Tier[i] ist ein ISpringer
dann (Tier[i] als ISpringer).springe;

Ich weiß allerdings nicht, wie es geht.

Doch, tust du. Steht alles schon da, wenn du das 1:1 nach Englisch (oder Pascal :D ) übersetzt:

ausblenden Delphi-Quelltext
1:
2:
if Tier[i] is ISpringer then
  (Tier[i] as ISpringer).springe;


Oder, schöner (und ggf. einfacher, wenn du mehrere Methoden aufrufen willst):
ausblenden Delphi-Quelltext
1:
2:
3:
4:
var Springtier: ISpringer;
{...}
  if Tier[i].QueryInterface(ISpringer, Springtier)=S_OK then 
    SpringTier.springe;

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
delphijanka Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 151

WinXP
D 2009 Arc., Java, C
BeitragVerfasst: Fr 17.09.10 16:51 
@Martok

Lösung (a):

- geht schon mal nicht: "Operator not applicable to this operand type"

Lösung (b):

- die Methode QueryInterface ist nicht bekannt.
- Was schreibe ich an der {...} - Stelle? Wie erzeuge ich ein Objekt von ISpringer?
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Fr 17.09.10 17:12 
(a) Könnte sogar stimmen, damit man sowas tun kann, braucht das Interface eine GUID. Steht irgendwo in der Delphi-Hilfe welche Tastenkombination das war und was genau man damit tun soll.

(b) Faszinierend. Das ist in TInterfacedObject wirklich protected. Dann eben anders und noch schöner :P

ausblenden Delphi-Quelltext
1:
2:
3:
4:
var Springtier: ISpringer;
{...}
  if Supports(Tier[i], ISpringer, Springtier) then 
    SpringTier.springe;


Anstelle der Auslassung dürfte wohl mindestens ein begin und ein for kommen. Aber das musst du schon wissen...

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
delphijanka Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 151

WinXP
D 2009 Arc., Java, C
BeitragVerfasst: Fr 17.09.10 17:15 
@Martok

Wie ich erstelle ich ein Objekt vom Interface-Typ. In diesem Fall vom ISpringer?
mkinzler
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 4106
Erhaltene Danke: 13


Delphi 2010 Pro; Delphi.Prism 2011 pro
BeitragVerfasst: Fr 17.09.10 19:05 
Man kann kleine Instanzen von Interfacen erzeugen. Du musst eine Klasse von dem Interface ableiten und diese dann instantiieren

_________________
Markus Kinzler.
delphijanka Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 151

WinXP
D 2009 Arc., Java, C
BeitragVerfasst: Mo 20.09.10 00:55 
@Martok und mkinzler:

Die Prozeduren QueryInterface oder Supports erwarten Interface-Parameter vom Typ TGuid, wogegen ISpringer nicht von diesem Typ ist.
Daher kommt die Fehlermeldung. Gibt es denn keine Lösung für mein Problem in Delphi? Muss ich unbedingt die Deklaration mit TGuid machen?
(Warum ist das in Delphi nur so kompliziert?... :( ). Wäre sehr dankbar für eine funktionierende Lösung.
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Mo 20.09.10 01:11 
user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
(a) Könnte sogar stimmen, damit man sowas tun kann, braucht das Interface eine GUID. Steht irgendwo in der Delphi-Hilfe welche Tastenkombination das war und was genau man damit tun soll.

Hilfeseiten dazu: "Schnittstellentypen" (kriegt man bei F1 auf "interface") und "Identifikation einer Schnittstelle" von da aus.

Sobald du das Interface identifizierbar gemacht hast durch Vergabe eine GUID kannst du es anstelle von GUIDs verwenden.

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mo 20.09.10 12:22 
Wenn du innerhalb der Hierarchie bleibst und nicht irgendwie quer oder hoch castest, dann kannst du einfach ILaufer(...) schreiben und brauchst auch keine GUIDs.

Also von TTier auf ISpringer brauchst du GUIDs, von TLeopard nicht. Hängt ein wenig vom Anwendungsfall ab.
delphijanka Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 151

WinXP
D 2009 Arc., Java, C
BeitragVerfasst: Fr 24.09.10 15:08 
zu der Lösung, wie Martok sie vorgeschlagen hat, eine kleine Abwandlung, die
ich in meinem Prog benutze:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
var
  SpringTier: IPDFErzeuger;
  Unk: IUnknown;
begin
if Tier[i].GetInterface(IUnknown, Unk) and Supports(Unk, ISpringer, SpringTier) then 
  SpringTier.springe;

Und dabei habe ich ein Problem: das Objekt Tier[i] wird nach diesem Code automatisch freigegeben. Liegt es an Referenzzählung? Wie kann ich erreichen, dass es nicht freigegeben wird (ich muss Tier[i] ja weiter benutzen...)
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Fr 24.09.10 15:42 
Hat mich auch schon viele Nerven gekostet...
nimm TinterFacedPersistent, dann tickt es so wie wir es wollen.
delphijanka Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 151

WinXP
D 2009 Arc., Java, C
BeitragVerfasst: So 26.09.10 17:51 
@bummi

Bei der Nutzung von TInterfacedPersistent kommt der Fehler, der Bezeichner sei undefiniert.
(benutze zur Zeit Delphi 5)