Ich habe eine vorhandene Klasse, die interagiert und eine Datei öffnen, lesen oder schreiben kann. Ich muss eine Dateimodifikation abrufen, um eine neue Methode hinzuzufügen
Angenommen, dies ist meine Klassendefinition, in der ich eine neue Methode hinzufügen möchte.
class IO_file
{
std::string m_file_name;
public:
IO();
IO(std::string file_name);
+ time_t get_mtime(file_name);
+ OR
+ time_t get_mtime();
};
Ich habe zwei Möglichkeiten -
Erstellen Sie ein leeres Objekt und übergeben Sie den Dateinamen in dem Methodenargument, für das ich die Änderungszeit der Datei abrufen möchte.
Übergeben Sie den Dateinamen bei der Objektkonstruktion und rufen Sie einfach die Elementfunktion auf, die für die Elementvariable ausgeführt wird.
Beide Optionen erfüllen den Zweck. Ich glaube auch, dass der zweite Ansatz besser ist als der erste. Aber was ich nicht verstehe ist wie ? Ist der erste Ansatz schlechtes Design, da keine Mitgliedsvariable verwendet wird? Welches Prinzip des objektorientierten Designs verletzt es? Wenn eine Mitgliedsfunktion die Mitgliedsvariable nicht verwendet, sollte diese Mitgliedsfunktion immer statisch gemacht werden?
IO("somefile.txt").get_mtime("someotherfile.txt")
. Was bedeutet das überhaupt?Antworten:
Nein.
OOP ist es egal, ob Ihre Mitgliedsfunktion Klasseneigenschaften oder Mitgliedsvariablen verwendet oder nicht verwendet. OOP kümmert sich um Polymorphismus und nicht um die Implementierung einer harten Codierung. Statische Funktionen haben ihre Verwendung, aber eine Funktion sollte nicht statisch sein, nur weil sie nicht vom Objektstatus abhängt. Wenn das dein Denken ist, aber beschuldige OOP nicht, weil diese Idee nicht von OOP kam.
Wenn Sie sich den Status nicht von Anruf zu Anruf merken müssen, gibt es keinen guten Grund, den Status zu verwenden.
Keiner.
Nein. Bei diesem Denken geht der Implikationspfeil in die falsche Richtung.
Eine statische Funktion kann nicht auf den Instanzstatus zugreifen
Wenn die Funktion nicht auf den Instanzstatus zugreifen muss, kann die Funktion statisch oder nicht statisch sein
Es liegt ganz bei Ihnen, die Funktion hier statisch zu machen. Aber es wird es eher wie ein globales, wenn Sie dies tun. Bevor Sie statisch werden, sollten Sie die Funktion in einer zustandslosen Klasse hosten. Es ist flexibler.
Ich habe hier ein OOP-Beispiel für eine Member-Funktion, die keine Klasseneigenschaften oder Member-Variablen verwendet.
Die Mitgliedsfunktion (und ihre zustandslose Klasse) :
Drei verschiedene Implementierungen:
Ein Ort zum Speichern der Wahl der Implementierung:
Ein Anwendungsbeispiel
Ausgänge:
Und das alles, ohne
execute()
sich um den Zustand eines Objekts zu kümmern. DieStrategy
Klasse ist eigentlich staatenlos. Nur Staat ist inContext
. Staatenlose Objekte sind in OOP vollkommen in Ordnung.Diesen Code haben Sie hier gefunden .
quelle
get_mtime
wäre hier als eigenständige Funktion oder alsstatic
Funktion sinnvoller , als wie Sie hier gezeigt haben.Die
mtime
Datei wird auf den meisten Systemen von einem Aufruf anlstat
oder ähnlich gelesen und erfordert keinen offenen Dateideskriptor. Daher ist es nicht sinnvoll, sie als Elementfunktion einer instanziierten Klasse zu haben.quelle
static
.Der Grund, warum die zweite Option instinktiv besser erscheint (und IMO besser ist), ist, dass Ihre erste Option Ihnen ein Objekt gibt, das eigentlich nichts darstellt.
Wenn Sie den Dateinamen nicht angeben, ist Ihre IO_file-Klasse eigentlich nur ein abstraktes Objekt, das zufällig einer konkreten Datei ähnelt. Wenn Sie beim Aufrufen der Methode den Dateinamen übergeben, können Sie stattdessen auch einfach die gesamte Methode in eine frei schwebende reine Funktion umgestalten. Es hat keinen wirklichen Vorteil, es an ein Objekt gebunden zu halten, das Sie instanziieren müssen, um es zu verwenden. Es ist nur eine Funktion; Das Objekt-Instanziierungs-Boilerplate ist nur ein unpraktischer zusätzlicher Schritt.
Wenn dem Dateinamen jedoch alle Methoden zugewiesen wurden, die Sie für dieses Objekt aufrufen, ähneln sie eher Abfragen zu einer bestimmten Instanz einer Sache. Das ist besser OO, weil Ihre Objekte eine tatsächliche Bedeutung und daher einen Nutzen haben.
quelle
Lassen Sie uns dies in C übersetzen. Zuerst haben wir unsere Klasse - jetzt ist es eine Struktur:
Definieren wir zur Vereinfachung der Snippets eine Konstruktorfunktion (wobei Speicherlecks vorerst ignoriert werden):
Option 2 sieht folgendermaßen aus:
und so verwendet:
Wie wäre es mit Option 1? Nun, es sieht so aus:
Und wie wird es verwendet? Im Wesentlichen möchten Sie Junk als ersten Parameter übergeben:
Macht nicht viel Sinn, oder?
Das Objektsystem von C ++ verbirgt es, aber das Objekt ist auch ein Argument der Methode - ein implizites Zeigerargument mit dem Namen
this
. Dies ist, was Option 1 schlecht ist - sie hat ein Argument, das per Definition nicht verwendet wird (Argumente, die zufällig nicht verwendet werden, aber möglicherweise bei Überschreibungen verwendet werden, sind in Ordnung). Solche Argumente tragen nichts dazu bei, während sie die Signatur, Definition und Verwendung der Funktion komplizieren und die Leser des Codes verwirren, die darüber nachdenken, was das Argument tun soll, warum es in Ordnung ist, Junk an das Argument weiterzugeben und ob Sie es sind oder nicht Das Übergeben von Junk /NULL
/ Leerzeichen an dieses Objekt ist die Ursache für den Fehler, den sie derzeit zu lösen versuchen. Spoiler - ist es nicht, aber sie werden immer noch Zeit damit verschwenden, diese Möglichkeit zu erkunden.Die Tatsache, dass das Junk-Argument implizit ist, kann den Effekt verringern, ist aber immer noch vorhanden und kann durch die Erstellung der Methode leicht vermieden werden
static
.quelle