Einzelnen Beitrag anzeigen

Benutzerbild von Gausi
Gausi

Registriert seit: 17. Jul 2005
880 Beiträge
 
Delphi 11 Alexandria
 
#1

Methoden in abgeleiteten Klassen ggf. einschränken

  Alt 11. Jul 2024, 18:49
Ich bin gerade dabei, eine meiner Klassensammlungen etwas zu überarbeiten - es geht dabei um das Auslesen und Bearbeiten von Metadaten (aka "ID3-Tags") in Audio-Dateien. Vor ein paar Jahren habe ich einer ersten grundlegenden Überarbeitung einige Properties über eine abstrakte Basisklasse TAudioFile bereitgestellt. Die Getter und Setter für Dinge wie "Interpret" und "Album" und die Hauptmethoden "ReadFromFile" und "WriteToFile" werden in abgeleiteten Klassen wie TMp3File oder TFlacFile implementiert. Das dann kombiniert mit einer Factory-Klasse, und man muss praktisch nichts mehr über die unterschiedlichen Audioformate wissen, um die "einfachen" Daten auszulesen und zu verändern.
Delphi-Quellcode:
aAudioFile := AudioFileFactory.CreateAudioFile(aFileName);
aAudioFile.ReadFromFile(aFileName);
aAudioFile.Title := EditTitle.Text;
aAudioFile.UpdateFile;
// fertig.
Soweit so gut. Ich würde die Funktionalität der Basisklasse gerne erweitern, und da stoße ich auf ein kleines Konzept-Problem.

Ziel: Statt nur klar definierte Eigenschaften wie "Interpret" und "Titel" möchte ich auch über die Basisklasse eine Funktion anbieten wie "Liste mit (fast) allen Metadaten".

In den unterschiedlichen Audioformaten kommen unterschiedliche Tagging-Formate zum Einsatz. Von ID3-Tags haben wohl viele schon was gehört. Dann gibt es Vorbis-Kommentare, Apev2-Tags und in M4a-Dateien nennt sich das "Meta-Atom" (oder so ähnlich). Abstrakt runtergebrochen findet sich in allen Systemen (vom rudimentären ID3v1-Tag mal abgesehen) eine Liste von "TTagItems". Jedes TagItem besitzt eine Art "Key", der etwas über die Bedeutung des Inhalts verrät, und dann eben entsprechende Daten. Häufig sind die Daten vom Typ "Text", manchmal "Text mit Metadaten", aber auch "Bild", "Bild mit Metadaten" oder einfach nur "Daten".

Die Basisklasse TAudioFile müsste also eine Methode bekommen
Delphi-Quellcode:
// alle TagItems in eine Liste einfügen
procedure GetAllTagItems(dest: TTagItemList);
Die Objekte vom Typ TTagItem darin bräuchten dann für die Anzeige und zum Bearbeiten Methoden wie
Delphi-Quellcode:
function TTagItem.GetText: String;
procedure TTagItem.SetText(Value: String);
Die müssten dann in den konkreten abgeleiteten Klassen wie TID3v2TagItem oder TOggVorbisCommentTagItem implementiert werden. Eigentlich ja kein Problem - wenn alle TagItems nur "Text" enthielten. Das ist aber nicht der Fall. Z.B. kann ein ID3v2Tag ein TagItem mit dem Key "APIC" enthalten, in dem dann ein Bild steckt. Wenn nun aber das TID3v2TagItem von TTagItem abgeleitet ist, dann kann man auch darauf SetText anwenden, und damit den Inhalt des Picture-Items ungültig machen. Das wäre irgendwie doof.

Frage: wie kann man halbwegs sicherstellen, dass der Anwender der Bibliothek (das schließt mich mit ein ) später keinen Mist damit baut (es sei denn, er legt es ausdrücklich darauf an)?

Meine Idee wäre, in der konkreten Implementierung von "TSomeTagItem.SetText" zu überprüfen, ob das TagItem mit dem aktuell gesetzten Key überhaupt Textdaten enthält (das wird über den jeweiligen Standard bzw. die Dokumentation geregelt). Falls ja: ok, fein. Und falls nein? Einfach "nichts" machen? Aus der Set-Procedure eine Function machen und "False" zurückliefern? Eine Exception schmeißen?

Gibt es da eine andere Möglichkeit, die ggf. "sauberer" oder eleganter ist?

Eine Variante procedure GetAll_Text_TagItems(dest: TTagItemList); wird es natürlich auch geben.

(Das Problem besteht in der aktuellen Version der Library auch schon. Ist dort aber nicht so tragisch, da der Zugriff auf "Tag-Ebene" nicht so einfach ist. Das geht nur, wenn man sich etwas mehr mit den unterschiedlichen Formaten auseinandersetzt.)
The angels have the phone box.
  Mit Zitat antworten Zitat