[gelöst]Implementation eines Interfaces macht Probleme

Für Fragen von Einsteigern und Programmieranfängern...
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]Implementation eines Interfaces macht Probleme

Beitrag von Marsmännchen »

Hi,

ich weiß nicht weiter. Ich bekomme beim Kompilieren folgende Meckerliste:
Projekt kompilieren, Ziel: Taschenrechner.exe: Exit code 1, Fehler: 6
rechner.pas(15,16) Error: No matching implementation for interface method "QueryInterface(constref TGuid;out <Formal type>):LongInt; StdCall;" found
rechner.pas(15,16) Error: No matching implementation for interface method "_AddRef:LongInt; StdCall;" found
rechner.pas(15,16) Error: No matching implementation for interface method "_Release:LongInt; StdCall;" found
rechner.pas(15,16) Error: No matching implementation for interface method "registrieren(IAusgabeBeobachter);" found
rechner.pas(15,16) Error: No matching implementation for interface method "abmelden(IAusgabeBeobachter);" found
rechner.pas(15,16) Error: No matching implementation for interface method "informieren;" found
Es ist folgendes passiert:
Ich HABE alle Methoden des angemeckerten Interfaces in meiner Klasse implementiert (geht um die Implementierung eines Observerpatterns). Ich habe es aber auch in meiner jugendlichen Unschuld gewagt, danach eine der Interface-Methoden ("informieren") umzubenennen. Ich vermute, dass das Problem damit zusammenhängt, denn wenn man sich die letzte Meldung des Kompilers ansieht, dann fällt auf, dass nach der Methode "informieren" kein Verweis mehr auf das Interface erfolgt, wie bei den anderen Methoden. Ich habe aber keinen Schimmer, wie ich das weg bekomme. Ich habe die Procedure zurückbenannt, ich habe es mit Aufräumen und kompilieren versucht. Die Meckerliste bleibt immer gleich.

Googlesuche hat mir nicht geholfen. Es gab zu diesen Fehlermeldungen sogar einen Verweis auf unser Forum, aber da ging es um die Installation der zeoslib (was immer das sein mag) :cry:

Was muss ich tun?
(Quellcode poste ich erstmal nicht, weil ich glaube, mit dem hat das eher weniger zu tun. Kann ich aber gerne nachholen, falls gewünscht)
Zuletzt geändert von Marsmännchen am So 21. Feb 2016, 21:52, insgesamt 1-mal geändert.
Ich mag Pascal...

Mathias
Beiträge: 6918
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Implementation eines Interfaces macht Schwierigkeiten

Beitrag von Mathias »

Quellcode poste ich erstmal nicht, weil ich glaube, mit dem hat das eher weniger zu tun.
Es wäre interessant, wie der Quellcode, bei rechner.pas(15/16) aussieht.
Ansonsten kann man nicht gross helfen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

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: Implementation eines Interfaces macht Schwierigkeiten

Beitrag von Marsmännchen »

Okay, hier:

Code: Alles auswählen

 
unit Rechner;
 
{$mode objfpc}{$H+}
 
interface
Type
    IAusgabeBeobachter = interface
      Procedure aktualisiere;
    end;
    IAusgabeSender = interface
      Procedure registrieren(beobachter:IAusgabeBeobachter);
      Procedure abmelden(beobachter:IAusgabeBeobachter);
      Procedure informieren;
    end;
    TRechner = class(IAusgabeSender)
      private
        FEingabestapel   : array of char;
        FAusgabeBeobachter:array of IAusgabeBeobachter;
        FErlaubteZeichen : set of char;
        FOperatoren      : set of char;
        FZahlen          : set of char;
        FIstNeuerAusdruck: Boolean;
        FAusgabeText     : string;
        FAusgabeZahl     : double;
        Function Ausgabe : string;
        Function Ausgabe : double;
        Function SemantikIstOkay(zeichen:char): Boolean;
        (* Ich brauche jetzt noch eine interne Funktion, um ein Ereignis
         * auszulösen, damit die Beobachter
         * mitbekommen, dass sich die Ausgabe geändert hat! *)
      public
        Constructor neu;
        Property textAusgabe   : String read Ausgabe;
        Property zahlenAusgabe : Double read Ausgabe;
        Procedure anfuegen(zeichen : char);
        Procedure loeschen;
    end;
 
 
 
implementation
 
uses
  Classes, SysUtils;
 
Constructor TRechner.neu;
begin
  FAusgabeText:= '';
  FAusgabeZahl:= 0.0;
  FZahlen := ['0','1','2','3','4','5','6','7','8','9'];
  FOperatoren      := ['+', '-', '*', '/'];
  FErlaubteZeichen :=  FZahlen + FOperatoren + ['='];
  FIstNeuerAusdruck:=True;
end;
 
Function TRechner.Ausgabe : String;
begin
 
   Result := FAusgabeText;
end;
Function TRechner.Ausgabe : Double;
begin
   Result := FAusgabeZahl;
end;
 
Procedure TRechner.anfuegen(zeichen : char);
var
  laenge : Integer;
begin
  if SemantikIstOkay(zeichen) then
  begin
    laenge := length(FEingabeStapel);
    setLength(FEingabeStapel, laenge + 1);
    FEingabeStapel[laenge] := zeichen;
    if FIstNeuerAusdruck then
       FAusgabeText:=zeichen
    else
       FAusgabeText:=FAusgabeText + zeichen;
    (* Hier noch Änderung der Ausgabe vornehmen und Ereignis auslösen
     * So auch in allen anderen Funktionen, die die Ausgabe verändern
     * können. Somit ist also eine Funktion angezeigt, die das für alle
     * übernimmt! *)
  end;
 
 
end;
 
Procedure TRechner.loeschen;
var
  laenge : Integer;
begin
  laenge := length(FEingabeStapel);
  setLength(FEingabeStapel, laenge-1);
end;
 
Function TRechner.SemantikIstOkay(zeichen:char) : Boolean;
const
  Ergebnis : Boolean = True;
begin
  if not(zeichen in FErlaubteZeichen) then
     Ergebnis := False;
  // Hier folgen dann noch Prüfungen zur Reihenfolge/Klammer usw.
  Result := Ergebnis;
end;
 
(* Routinen für IAusgabeSender  *)
Procedure TRechner.registrieren(Beobachter:IAusgabeBeobachter);
var
  laenge:Integer;
begin
  laenge := length(FAusgabeBeobachter);
  SetLength(FAusgabeBeobachter, laenge+1);
  FAusgabeBeobachter[laenge] := Beobachter;
end;
 
Procedure TRechner.abmelden(Beobachter:IAusgabeBeobachter);
var
  laenge,i,j:Integer;
begin
  laenge = High(FAusgabeBeobachter);
  for i:=0 to laenge do
  begin
    if FAusgabeBeobachter[i] = Beobachter then
    begin
      for j:=i to (laenge-1) do
        FAusgabeBeobachter[j]:=FAusgabeBeobachter[j+1];
      SetLength(FAusgabeBeobachter, laenge-1);
      break;
    end;
  end;
end;
 
Procedure TRechner.informieren;
var
  i:integer;
begin
  for i:=0 to High(FAusgabeBeobachter) do
    FAusgabeBeobachter[i].aktualisiere;
end;
 
end.
 
 
Ich mag Pascal...

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2813
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: Implementation eines Interfaces macht Schwierigkeiten

Beitrag von m.fuchs »

Keine der drei Interface-Methoden ist in der Definition deiner Klasse enthalten. Du implementierst sie zwar, aber sie müssen natürlich auch definiert werden.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

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: Implementation eines Interfaces macht Schwierigkeiten

Beitrag von Marsmännchen »

Das war's! Typischer Anfängerfehler. Ich ging unbewusst davon aus, dass durch die Einbindung des Interfaces klar wäre, dass diese Methoden implementiert werden müssen. So wäre es auch in anderen Sprachen ohne Vorwärtsdeklaration (um das klar zu sagen: ich mag die saubere Codestrukturierung in Pascal sehr). So im Nachhinein ist es aber logisch.

Die Compilermeldung "No matching implementation for interface method ... found" finde ich dabei - zumindest für Anfänger - nicht so hilfreich, weil sie den Fehler nur sehr allgemein beschreibt. Nun ja, wahrscheinlich geht es nicht besser. Ich muss halt lernen, in Pascal immer an beide möglichen Problemfelder zu denken (also, ob Deklaration und Implementation korrekt sind).

Mit den Deklarationen habe ich übrigens die ersten drei Fehlermeldungen nicht wegbekommen. Hier hat mir dann aber ein Blick in die Referenz geholfen. Ich habe meine Klasse jetzt von TInterfacedObject abgeleitet. Jetzt funzt alles.

Ich hoffe, diese Anfängerfragen nerven nicht zu sehr, aber ich habe hierdurch wieder viel gelernt. Die Lernschiene: Ausprobieren, selber versuchen die Probleme zu lösen, dann ggf. a littel help from my friends :wink: ... ist sehr effektiv.

Dankeschön!
Ich mag Pascal...

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2813
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: Implementation eines Interfaces macht Schwierigkeiten

Beitrag von m.fuchs »

Marsmännchen hat geschrieben:Mit den Deklarationen habe ich übrigens die ersten drei Fehlermeldungen nicht wegbekommen. Hier hat mir dann aber ein Blick in die Referenz geholfen. Ich habe meine Klasse jetzt von TInterfacedObject abgeleitet. Jetzt funzt alles.
Alternativ fügst du folgendes in deiner Unit ein:

Code: Alles auswählen

 {$INTERFACES CORBA}
Dann kannst du dir die Ableitung von TInterfacedObject ersparen. Der Kram wird nur für die Referenzzählung benötigt. Leider musste irgendein bekiffter Trottel bei Borland das seinerzeit so implementieren.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

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: [gelöst]Implementation eines Interfaces macht Probleme

Beitrag von Marsmännchen »

Okay, ich habe mir die Direktive mal in der Referenz angesehen. Irgendwann werde ich auch diesen Referenzzählkram verstehen, aber der ist für mich vermutlich derzeit nicht wichtig. Als der Borland-Programmierer das so festgelegt hat, dachte er wahrscheinlich: "Geile Farben!" :mrgreen:
Ich mag Pascal...

Antworten