Hallo,
ich erhalte in einer Programmbibiliothek für mehrere Methoden, die in der Basisklasse definitiv vorhanden sind, die im Threadtitel genannte Fehlermeldung. In der Basisklasse sind die fraglichen Methoden als virtual; abstract; mit derelben Parameterliste definiert, wie in der abgeleiteten Klasse, wo sie überschrieben werden sollen, um definiert zu werden. In abgeleiteter, wie in der Basisklasse auch sind die fraglichen Methoden in derselben Sichtbarkeitsstufe.
Warum erhalte ich da die besagte Fehlermeldung?
myeunit.pas(210,17) Error: There is no method in an ancestor
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1430
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: myeunit.pas(210,17) Error: There is no method in an ance
Definitiv nicht. Poste doch mal ein nachvollziehbares Beispiel.
Re: myeunit.pas(210,17) Error: There is no method in an ance
.
Ok, hier das Beispiel. Dieses hier funktioniert. Was also kann da schief laufen? Wo muss ich in meiner komplexeren Klassenbibliothek genauer hinschauen. Denn auch in dieser gibt es die betroffenen Methoden mit exakt gleicher Parameterliste und exakt gleichen Namen wie auch exakt als Function bzw Procedure sowohl als virtual; abstract; als auch als override;
In diesem Beispiel funktioniert es.
In meiner realen Klassenbibliothek sagt mir der Compiler nun aber, dass es keine Methoden zum Überschreiben gäbe.
Warum funktioniert das hier, aber nicht in meiner komplexeren Klassenbibliothek. Ich habe dort nur einige vorausgesetzte Units verändert, die jedoch keinerlei andere Klassendefinitionen enthalten. Was also kann da noch schief laufen. Ich hatte diesen Fehler schon mal vor längerer Zeit bei einer anderen Klassenbibliothek.
In der besagten komplexeren Klassenbibliothek befinden sich Basisklasse und abgeleitete Klasse in zwei verschiedenen Units.
.
Ok, hier das Beispiel. Dieses hier funktioniert. Was also kann da schief laufen? Wo muss ich in meiner komplexeren Klassenbibliothek genauer hinschauen. Denn auch in dieser gibt es die betroffenen Methoden mit exakt gleicher Parameterliste und exakt gleichen Namen wie auch exakt als Function bzw Procedure sowohl als virtual; abstract; als auch als override;
Code: Alles auswählen
type
TMyBaseClass = class(TObject)
private
FAnyField: Integer;
protected
function GetTheFildValue: Integer; virtual; abstract;
public
procedure SetTheFieldValue(Value: Integer); virtual; abstract;
end;
TMyClass = class(TMyBaseClass)
protected
function GetTheFildValue: Integer; override;
public
procedure SetTheFieldValue(Value: Integer); override;
end;
{ TMyClass }
function TMyClass.GetTheFildValue: Integer;
begin
end;
procedure TMyClass.SetTheFieldValue(Value: Integer);
begin
end;
In diesem Beispiel funktioniert es.
In meiner realen Klassenbibliothek sagt mir der Compiler nun aber, dass es keine Methoden zum Überschreiben gäbe.
Warum funktioniert das hier, aber nicht in meiner komplexeren Klassenbibliothek. Ich habe dort nur einige vorausgesetzte Units verändert, die jedoch keinerlei andere Klassendefinitionen enthalten. Was also kann da noch schief laufen. Ich hatte diesen Fehler schon mal vor längerer Zeit bei einer anderen Klassenbibliothek.
In der besagten komplexeren Klassenbibliothek befinden sich Basisklasse und abgeleitete Klasse in zwei verschiedenen Units.
.
-
- Beiträge: 1908
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: myeunit.pas(210,17) Error: There is no method in an ance
thosch hat geschrieben:In diesem Beispiel funktioniert es.
In meiner realen Klassenbibliothek sagt mir der Compiler nun aber, dass es keine Methoden zum Überschreiben gäbe.
[...]
In der besagten komplexeren Klassenbibliothek befinden sich Basisklasse und abgeleitete Klasse in zwei verschiedenen Units.
Ein funktionierendes beispiel bringt ja herzlich wenig. Nimm doch einfach mal deine komplexe klassenbibliothek und reduzier sie, statt ein neues funktionierendes beispiel zu schreiben.
Begin erst mal damit das du die gesammte implementation rauswirfst, die hat mit dem problem nix zu tun. Dann wirfst du alle klassen raus die nicht mit dieser klasse zusammenhängen.
Jetzt sollte der Fehler ja immernoch auftreten, nur du hast schonmal den großteil deiner bibliothek eliminiert.
Dann wirf immer mehr raus. Sei dabei nicht kleinschrittig, sondern geh einfach in die datei und werf einfach mal die hälfte der zeilen raus. Wenn dardurch neue fehler reinkommen (z.B. bezeichner die gebraucht werden hast du rausgeworfen) ersetz die bezeichner durch andere, Z.B. kannst du klassennamen durch TObject ersetzen.
Wenn beim rauswerfen der fehler nicht mehr auftaucht, weist du das er in dem Teil vom code war, ansonsten nimm dir wieder ne hälfte an zeilen code und wirf die raus. Am ende sollte aus deiner komplizierten Klassenbibliothek nur noch ein paar klassen rauskommen.
Sachen die du rauswerfen kannst:
1. Andere klassen, die vorkomnisse dieser klassen einfach durch TObject ersetzen (da die implementation rausgeflogen ist, macht das ja eh nix aus)
2. Stufen in Klassenhierachien. Sagen wir du hast klasse A, B, C A erbt von B erbt von C, und der fehler ist in A und C (also A implementiert ne abstrakte methode von C) dann kannst du B einfach rausschmeißen und A direkt von C erben lassen. Wenn A aus B implementiert kannst du C einfach rausschmeißen, und wenn B von C, kannst du A rausschmeißen
3. Felder und andere funktionen. Ohne implementierung brauchst du keine daten, also kannst du alle variablen/Felder deiner Klassen schonmal von anfang an rausschmeißen. Da das ein vererbungs problem ist auch alle funktionen die nicht virtual oder override sind.
Selbst wenn du ne 10,000 zeilen Klassenbibliothek hast, solltest du (wenn du immer genau die hälfte an zeilen rausschmeißt) nach maximal 15 rausschmeißoperationen deinen fehler gefunden haben. (Für C gibt es sogar programme die das voll automatisch machen, für pascal leider meines wissens nach nicht). Du musst halt in jedem schritt schauen ob der fehler noch auftritt, wenn nicht hast du was gelöscht was dafür gesorgt hat das der fehler auftritt. Wenns z.B. ein FPC bug wäre, kann es sein das ganz andere klassen den hervorrufen. Also immer hälfte löschen, kompilieren->Fehler noch da?: Nächste hälfte löschen, fehler nicht mehr da? dann weist du der fehler, oder ein teil des fehler ist in dieser hälfte, fängst also an diese hälfte zu reduzieren. Egal welcher der beiden fälle eintritt, in jedem schritt musst du nur noch die hälfte des codes betrachten
Der fehler den du hast, entsteht vor allem im klassen parsen, wird also bereits vor dem Forward definiton nicht gefunden fehler geworfen, was bedeutet das du sogar wirklich alles unterhalb von implementation rauswerfen kannst, da das diesen fehler nicht beeinflussen kann (und der compiler wird deinen fehler finden bevor er meckert das es keine implementation gibt).
Und wenn du ein reduziertes beispiel hast, und den fehler dann nicht schon selbst gefunden hast (meist lacht der einen ins gesicht wenn man erst mal alles reduziert hat), kannst du dann doch das hier posten.
Re: myeunit.pas(210,17) Error: There is no method in an ance
Danke erst mal so weit, da weiß ich wenigstens erst mal, wo ich mit der Fehlersuche ansetzen muss bzw. wie ich da vorgehen muss
Mach ich morgen. Wenn Fehler gefunden, poste ich das mit Fehlerursache gerne hierher.
Mach ich morgen. Wenn Fehler gefunden, poste ich das mit Fehlerursache gerne hierher.
Re: myeunit.pas(210,17) Error: There is no method in an ance
Hallo,
ich wollte doch noch mal eine Rückmeldung geben, wenn ich die Fehlerursache gefunden habe.
In meiner Klassenbibliothek hatte ich in einer der Units vorausgesetzte Units ausgetauscht. In einer der neu vorausgesetzten Units wurde ein Datentyp neu definiert. Nun war aber die Basisklasse in einer weiteren Unit definiert, die auch weiterhin vorausgesetzt wird und auch in der Uses Klausel enthalten ist. Aber in der Basisklasse wurde noch der vorherige gleichnamige Datentyp verwendet.
So hier:
In Basisklasse (In separater Unit):
Und nun die Unit, welche die Basisklasse ableitet:
Und weil nun zwar der Name des Datantyps in Basisklasse und abgeleiteter Klasse zwar gleich war, aber unterschiedlich definiert, hatte ich den Fehler.
.
ich wollte doch noch mal eine Rückmeldung geben, wenn ich die Fehlerursache gefunden habe.
In meiner Klassenbibliothek hatte ich in einer der Units vorausgesetzte Units ausgetauscht. In einer der neu vorausgesetzten Units wurde ein Datentyp neu definiert. Nun war aber die Basisklasse in einer weiteren Unit definiert, die auch weiterhin vorausgesetzt wird und auch in der Uses Klausel enthalten ist. Aber in der Basisklasse wurde noch der vorherige gleichnamige Datentyp verwendet.
So hier:
In Basisklasse (In separater Unit):
Code: Alles auswählen
unit meineBasisklasse;
Interface
Uses ...
type
TData = Integer;
TMyBaseClass = class
...
procedure DoSomething(withThis: TData); virtual; abstract;
...
end;
implementaion
....
end.
Und nun die Unit, welche die Basisklasse ableitet:
Code: Alles auswählen
unit myAncestrorClass;
uses
UAusgetauschteUnit;
type
TData = TMyRedefinedData;
TMyAncestorClass = class(TMyBaseClass)
...
procedure DoSomething(withThis: TData); override;
...
end;
implementation
....
end.
unit UAusgetauschteUnit;
interface
type
TMyRedefinedData = record
Data: String;
ID: Integer;
end;
implementation
end.
Und weil nun zwar der Name des Datantyps in Basisklasse und abgeleiteter Klasse zwar gleich war, aber unterschiedlich definiert, hatte ich den Fehler.
.