Warum sind private Felder für den Typ und nicht für die Instanz privat?

153

In C # (und vielen anderen Sprachen) ist es absolut legitim, auf private Felder anderer Instanzen desselben Typs zuzugreifen. Beispielsweise:

public class Foo
{
    private bool aBool;

    public void DoBar(Foo anotherFoo)
    {
        if (anotherFoo.aBool) ...
    }
}

Wie in der C # -Spezifikation (Abschnitte 3.5.1, 3.5.2) angegeben, erfolgt der Zugriff auf private Felder auf einem Typ und nicht auf einer Instanz. Ich habe dies mit einem Kollegen besprochen und wir versuchen, einen Grund zu finden, warum dies so funktioniert (anstatt den Zugriff auf dieselbe Instanz einzuschränken).

Das beste Argument, das wir finden könnten, sind Gleichheitsprüfungen, bei denen die Klasse möglicherweise auf private Felder zugreifen möchte, um die Gleichheit mit einer anderen Instanz zu bestimmen. Gibt es noch andere Gründe? Oder ein goldener Grund, der absolut bedeutet, dass es so funktionieren muss oder etwas völlig unmöglich wäre?

RichK
quelle
18
Was sind die Vorteile für die Alternative?
Jon Skeet
19
Es ist wahr, dass es die reale Welt nicht sehr gut modelliert. Nur weil mein Auto melden kann, wie viel Benzin noch übrig ist, heißt das nicht, dass mein Auto erkennen kann, wie viel Benzin JEDES Auto noch hat. Ja, ich kann theoretisch einen Zugriff auf eine "private Instanz" sehen. Ich habe das Gefühl, dass ich es wirklich nie verwenden würde, weil ich mir Sorgen machen würde, dass ich in 99% der Fälle wirklich möchte, dass eine andere Instanz auf diese Variable zugreift.
Aquinas
2
@Jon Die Position, die für die sogenannten "Vorteile" eingenommen wurde, ist, dass Klassen den internen Status einer anderen Instanz nicht kennen sollten - unabhängig davon, dass es sich um denselben Typ handelt. Kein Vorteil per say, aber es gibt wahrscheinlich einen ziemlich guten Grund, einen über den anderen zu wählen, und das haben wir versucht herauszufinden
RichK
4
Sie können die Variable jederzeit in ein Paar von Getter / Setter-Abschlüssen verwandeln, die im Konstruktor initialisiert wurden. Dies schlägt fehl, wenn dies nicht das gleiche ist wie während der Initialisierung ...
Martin Sojka
8
Scala bietet private Instanzmitglieder - zusammen mit vielen anderen Zugriffsebenen, die in Java, C # und vielen anderen Sprachen nicht zu finden sind. Dies ist eine absolut legitime Frage.
Bruno Reis

Antworten:

73

Ich denke, ein Grund, warum dies so funktioniert, ist, dass Zugriffsmodifikatoren zur Kompilierungszeit funktionieren . Daher ist es nicht einfach festzustellen, ob ein bestimmtes Objekt auch das aktuelle Objekt ist oder nicht. Betrachten Sie beispielsweise diesen Code:

public class Foo
{
    private int bar;

    public void Baz(Foo other)
    {
        other.bar = 2;
    }

    public void Boo()
    {
        Baz(this);
    }
}

Kann der Compiler unbedingt herausfinden, dass dies othertatsächlich der Fall ist this? Nicht in allen Fällen. Man könnte argumentieren, dass dies dann einfach nicht kompiliert werden sollte, aber das bedeutet, dass wir einen Codepfad haben, auf den ein privates Instanzmitglied der richtigen Instanz nicht zugreifen kann, was meiner Meinung nach noch schlimmer ist.

Nur erfordern Typ-Ebene und nicht auf Objektebene Sichtbarkeit gewährleistet , dass das Problem handhabbar ist, sowie eine Situation zu machen , die wie es scheint , sollte funktionieren tatsächlich Arbeit.

EDIT : Danilel Hilgarths Argument, dass diese Argumentation rückwärts ist, hat sich bewährt. Sprachdesigner können die gewünschte Sprache erstellen, und Compiler-Autoren müssen sich daran anpassen. Abgesehen davon haben Sprachdesigner einen gewissen Anreiz, Compiler-Autoren die Arbeit zu erleichtern. (In diesem Fall ist es jedoch leicht zu argumentieren, dass auf private Mitglieder nur über this(entweder implizit oder explizit) zugegriffen werden kann .)

Ich glaube jedoch, dass dies das Problem verwirrender macht, als es sein muss. Die meisten Benutzer (ich selbst eingeschlossen) würden es unnötig einschränken, wenn der obige Code nicht funktioniert: Immerhin sind das meine Daten, auf die ich zugreifen möchte ! Warum sollte ich durchmachen müssen this?

Kurz gesagt, ich glaube, ich habe den Fall, dass es für den Compiler "schwierig" ist, übertrieben. Was ich wirklich vermitteln wollte, ist, dass die obige Situation so aussieht, als ob die Designer gerne arbeiten würden.

dlev
quelle
33
IMHO, diese Argumentation ist falsch herum. Der Compiler erzwingt die Regeln der Sprache. Es macht sie nicht. Mit anderen Worten, wenn private Mitglieder "Instanz privat" und nicht "Typ privat" wären, wäre der Compiler auf andere Weise implementiert worden, z. B. nur zulassen, this.bar = 2aber nicht other.bar = 2, da otherdies eine andere Instanz sein könnte.
Daniel Hilgarth
@ Daniel Das ist ein guter Punkt, aber wie ich bereits erwähnte, denke ich, dass diese Einschränkung schlimmer wäre als eine Sichtbarkeit auf Klassenebene.
dlev
3
@dlev: Ich habe nichts darüber gesagt, ob ich "private Instanz" -Mitglieder für eine gute Sache halte oder nicht. :-) Ich wollte nur darauf hinweisen, dass Sie argumentieren, dass eine technische Implementierung die Regeln der Sprache vorschreibt und dass diese Argumentation meiner Meinung nach nicht korrekt ist.
Daniel Hilgarth
2
@ Daniel Point genommen. Ich denke immer noch, dass dies eine gültige Überlegung ist, obwohl Sie natürlich richtig sind, dass die Sprachdesigner letztendlich herausfinden, was sie wollen, und Compiler-Autoren dem entsprechen.
dlev
2
Ich glaube nicht, dass das Compiler-Argument zutrifft. Es gibt Sprachen, die nur Instanz-Privat (wie Ruby) und Instanz-Privat und Klassen-Privat nach Wahl erlauben (wie Eiffel). Die Compiler-Generierung war für diese Sprachen nicht schwieriger oder einfacher. Weitere Informationen finden Sie auch in meiner Antwort im Thread.
Abel
61

Da der Zweck der in C # und ähnlichen Sprachen * verwendeten Kapselung darin besteht, die gegenseitige Abhängigkeit verschiedener Codeteile (Klassen in C # und Java) und nicht verschiedener Objekte im Speicher zu verringern.

Wenn Sie beispielsweise Code in eine Klasse schreiben, die einige Felder in einer anderen Klasse verwendet, sind diese Klassen sehr eng miteinander verbunden. Wenn Sie jedoch mit Code arbeiten, in dem Sie zwei Objekte derselben Klasse haben, besteht keine zusätzliche Abhängigkeit. Eine Klasse hängt immer von sich selbst ab.

All diese Theorie über die Kapselung schlägt jedoch fehl, sobald jemand Eigenschaften erstellt (oder Paare in Java abruft / setzt) ​​und alle Felder direkt verfügbar macht, wodurch Klassen so gekoppelt werden, als würden sie sowieso auf Felder zugreifen.

* Zur Klärung der Einkapselungsarten siehe Abels ausgezeichnete Antwort.

Goran Jovic
quelle
3
Ich glaube nicht, dass es fehlschlägt, wenn get/setMethoden bereitgestellt werden. Accessor-Methoden behalten weiterhin eine Abstraktion bei (der Benutzer muss nicht wissen, dass sich dahinter ein Feld befindet oder welche Felder sich möglicherweise hinter der Eigenschaft befinden). Wenn wir beispielsweise eine ComplexKlasse schreiben , können wir Eigenschaften zum Abrufen / Festlegen der Polarkoordinaten und ein weiteres Abrufen / Festlegen für kartesische Koordinaten verfügbar machen. Welche die Klasse darunter verwendet, ist dem Benutzer unbekannt (es könnte sogar etwas ganz anderes sein).
Ken Wayne VanderLinde
5
@ Ken: Es schlägt fehl, wenn Sie für jedes einzelne Feld eine Eigenschaft angeben, ohne darüber nachzudenken, ob es verfügbar gemacht werden soll.
Goran Jovic
@Goran Obwohl ich der Meinung bin, dass dies nicht ideal wäre, schlägt es dennoch nicht vollständig fehl, da Sie mit den Get / Set-Accessoren zusätzliche Logik hinzufügen können, wenn sich beispielsweise die zugrunde liegenden Felder ändern.
ForbesLindesay
1
"Weil der Zweck der Kapselung darin besteht, die gegenseitige Abhängigkeit verschiedener Codeteile zu verringern " >> Nr. Kapselung kann auch Instanzkapselung bedeuten, sie hängt von der Sprache oder der Denkschule ab. Eine der definitivsten Stimmen zu OO, Bertrand Meyer, hält dies sogar für die Standardeinstellung für private. Sie können meine Antwort auf meine Meinung zu Dingen überprüfen, wenn Sie möchten;).
Abel
@Abel: Ich habe meine Antwort auf Sprachen mit Klassenkapselung gestützt, weil OP nach einer von ihnen gefragt hat, und ehrlich gesagt, weil ich sie kenne. Danke für die Korrektur und für neue interessante Infos!
Goran Jovic
49

Zu diesem interessanten Thread wurden bereits einige Antworten hinzugefügt, aber ich habe den wahren Grund nicht gefunden, warum dieses Verhalten so ist, wie es ist. Lassen Sie es mich versuchen:

Damals

Irgendwo zwischen Smalltalk in den 80ern und Java Mitte der 90er Jahre reifte das Konzept der Objektorientierung. Das Verstecken von Informationen, das ursprünglich nicht als Konzept gedacht war, das nur OO zur Verfügung stand (erstmals 1978 erwähnt), wurde in Smalltalk eingeführt, da alle Daten (Felder) einer Klasse privat und alle Methoden öffentlich sind. Während der vielen neuen Entwicklungen von OO in den 90er Jahren versuchte Bertrand Meyer, einen Großteil der OO-Konzepte in seinem wegweisenden Buch Object Oriented Software Construction (OOSC) zu formalisieren, das seitdem als (fast) endgültige Referenz zu OO-Konzepten und Sprachdesign gilt .

Bei privater Sichtbarkeit

Laut Meyer sollte eine Methode einer definierten Gruppe von Klassen zur Verfügung gestellt werden (Seite 192-193). Dies führt offensichtlich zu einer sehr hohen Granularität des Versteckens von Informationen. Die folgende Funktion steht Klasse A und Klasse B sowie allen ihren Nachkommen zur Verfügung:

feature {classA, classB}
   methodName

Im Fall von privatesagt er Folgendes: Ohne einen Typ explizit als für seine eigene Klasse sichtbar zu deklarieren, können Sie in einem qualifizierten Aufruf nicht auf diese Funktion (Methode / Feld) zugreifen. Dh wenn xes sich um eine Variable handelt, x.doSomething()ist dies nicht zulässig. Unqualifizierter Zugriff ist natürlich innerhalb der Klasse selbst erlaubt.

Mit anderen Worten: Um den Zugriff einer Instanz derselben Klasse zuzulassen, müssen Sie den Methodenzugriff dieser Klasse explizit zulassen. Dies wird manchmal als instanzprivat gegenüber klassenprivat bezeichnet.

Instanz-privat in Programmiersprachen

Ich kenne mindestens zwei Sprachen, die derzeit verwendet werden und die das Verstecken von instanzprivaten Informationen im Gegensatz zum Verstecken von klassenprivaten Informationen verwenden. Eine davon ist Eiffel, eine von Meyer entworfene Sprache, die OO auf die Spitze treibt. Das andere ist Ruby, eine heutzutage weit verbreitete Sprache. In Ruby privatebedeutet: "privat für diese Instanz" .

Auswahlmöglichkeiten für die Sprachgestaltung

Es wurde vorgeschlagen, dass es für den Compiler schwierig sein würde, eine Instanz privat zuzulassen. Ich denke nicht, da es relativ einfach ist, qualifizierte Aufrufe von Methoden nur zuzulassen oder zu verbieten. Wenn für eine private Methode doSomething()zulässig ist und x.doSomething()nicht, hat ein Sprachdesigner die Nur-Instanz-Zugänglichkeit für private Methoden und Felder effektiv definiert.

Aus technischer Sicht gibt es keinen Grund, sich für die eine oder andere Art zu entscheiden (insbesondere wenn man bedenkt, dass Eiffel.NET dies mit IL tun kann, gibt es auch bei Mehrfachvererbung keinen inhärenten Grund, diese Funktion nicht bereitzustellen).

Natürlich ist es Geschmackssache, und wie andere bereits erwähnt haben, sind einige Methoden möglicherweise schwieriger zu schreiben, ohne dass private Methoden und Felder auf Klassenebene sichtbar sind.

Warum C # nur die Klassenkapselung und nicht die Instanzkapselung zulässt

Wenn Sie sich Internet-Threads zur Instanzkapselung ansehen (ein Begriff, der manchmal verwendet wird, um die Tatsache zu bezeichnen, dass eine Sprache die Zugriffsmodifikatoren auf Instanzebene im Gegensatz zur Klassenebene definiert), wird das Konzept häufig verpönt. Wenn man jedoch bedenkt, dass einige moderne Sprachen die Instanzkapselung verwenden, zumindest für den Modifikator für den privaten Zugriff, denken Sie, dass dies in der modernen Programmierwelt von Nutzen sein kann und ist.

Allerdings hat C # C ++ und Java für sein Sprachdesign zugegebenermaßen am härtesten untersucht. Während Eiffel und Modula-3 ebenfalls im Bild waren, glaube ich, dass sie angesichts der vielen fehlenden Funktionen von Eiffel (Mehrfachvererbung) dieselbe Route wie Java und C ++ gewählt haben, wenn es um den Modifikator für den privaten Zugriff ging.

Wenn Sie wirklich wissen möchten, warum Sie versuchen sollten, Eric Lippert, Krzysztof Cwalina, Anders Hejlsberg oder andere Personen zu erreichen, die am Standard von C # gearbeitet haben. Leider konnte ich in der kommentierten Programmiersprache The C # keinen endgültigen Hinweis finden .

Abel
quelle
1
Das ist eine schöne Antwort mit viel Hintergrund, sehr interessant, danke, dass Sie sich die Zeit genommen haben, auf eine (relativ) alte Frage zu antworten
RichK
1
@RichK: Gern geschehen, habe die Frage wohl zu spät gestellt, fand das Thema aber faszinierend genug, um mit einer gewissen Tiefe zu antworten :)
Abel
Unter COM bedeutete "privat" "instanz-privat". Ich denke, dies war in gewissem Maße so, weil eine Definition der Klasse Fooeffektiv eine Schnittstelle und eine implementierende Klasse darstellte. Da COM kein Konzept für eine Klassenobjektreferenz hatte - nur eine Schnittstellenreferenz -, konnte eine Klasse auf keinen Fall eine Referenz auf etwas enthalten, das garantiert eine andere Instanz dieser Klasse war. Dieses schnittstellenbasierte Design machte einige Dinge umständlich, aber es bedeutete, dass man eine Klasse entwerfen konnte, die durch eine andere ersetzt werden konnte, ohne dass sie dieselben Interna teilen musste.
Supercat
2
Gute Antwort. OP sollte erwägen, diese Frage als Antwort zu markieren.
Gavin Osborn
18

Dies ist nur meine Meinung, aber pragmatisch gesehen denke ich, wenn ein Programmierer Zugriff auf die Quelle einer Klasse hat, können Sie ihnen vernünftigerweise den Zugriff auf die privaten Mitglieder der Klasseninstanz anvertrauen. Warum die rechte Hand eines Programmierers binden, wenn Sie ihm in der linken bereits die Schlüssel zum Königreich gegeben haben?

FishBasketGordo
quelle
13
Ich verstehe dieses Argument nicht. Angenommen, Sie arbeiten an einem Programm, in dem Sie der einzige Entwickler sind und der einzige, der NIEMALS Ihre Bibliotheken verwenden würde. Wollen Sie in diesem Fall JEDES Mitglied öffentlich machen, weil Sie Zugriff auf den Quellcode haben?
Aquinas
@aquinas: das ist ganz anders. Alles öffentlich zu machen wird zu schrecklichen Programmierpraktiken führen. Das Zulassen, dass ein Typ private Felder anderer Instanzen von sich selbst sieht, ist ein sehr enger Fall.
Igby Largeman
2
Nein, ich befürworte nicht, jedes Mitglied öffentlich zu machen. Himmel nein! Mein Argument ist, wenn Sie bereits in der Quelle sind, die privaten Mitglieder sehen können, wie sie verwendet werden, verwendete Konventionen usw., warum dann nicht in der Lage sein, dieses Wissen zu nutzen?
FishBasketGordo
7
Ich denke, die Denkweise ist immer noch in der Art des Typs. Was kann der Typ tun, wenn ihm nicht vertraut werden kann, dass er ordnungsgemäß mit den Mitgliedern des Typs umgeht? ( Normalerweise wäre es ein Programmierer, der die Interaktionen tatsächlich kontrolliert, aber in Zeiten von Tools zur Codegenerierung ist dies möglicherweise nicht immer der Fall.)
Anthony Pegram
3
Meine Frage ist nicht wirklich Vertrauen, sondern Notwendigkeit. Vertrauen ist völlig irrelevant, wenn Sie Reflexion verwenden können, um abscheuliche Dinge für Privatpersonen zu tun. Ich frage mich, warum Sie konzeptionell auf die Privaten zugreifen können. Ich nahm an, dass es eher einen logischen Grund als eine Best-Practice-Situation gab.
RichK
13

Der Grund ist in der Tat Gleichheitsprüfung, Vergleich, Klonen, Überladen von Operatoren ... Es wäre sehr schwierig, Operator + beispielsweise für komplexe Zahlen zu implementieren.

Lorenzo Dematté
quelle
3
Aber alles, was Sie erwähnen, erfordert einen Typ, der den Wert eines anderen Typs erhält. Ich bin mit an Bord und sage: Sie wollen meinen Privatstaat inspizieren? Gut, mach weiter. Sie möchten meinen privaten Status festlegen ? Auf keinen Fall, Kumpel, ändere deinen eigenen verdammten Zustand. :)
Aquinas
2
@aquinas So funktioniert das nicht. Felder sind Felder. Sie sind nur schreibgeschützt, wenn sie als deklariert sind, readonlyund dies gilt auch für die deklarierende Instanz. Offensichtlich behaupten Sie, dass es eine bestimmte Compiler-Regel geben sollte, um dies zu verbieten, aber jede solche Regel ist eine Funktion, die das C # -Team spezifizieren, dokumentieren, lokalisieren, testen, warten und unterstützen muss. Wenn es keinen zwingenden Nutzen gibt, warum sollten sie es dann tun?
Aaronaught
Ich stimme @Aaronaught zu: Die Implementierung jeder neuen Spezifikation und die Änderung des Compilers sind mit Kosten verbunden. Betrachten Sie für ein festgelegtes Szenario eine Klonmethode. Sicher, Sie möchten es vielleicht mit einem privaten Konstruktor realisieren, aber in einigen Szenarien ist es möglicherweise nicht möglich / ratsam.
Lorenzo Dematté
1
C # Team? Ich diskutiere nur mögliche theoretische Sprachänderungen in JEDER Sprache. "Wenn es keinen zwingenden Vorteil gibt ..." Ich denke, es kann einen Vorteil geben. Wie bei jeder Compiler-Garantie kann es für jemanden nützlich sein, zu garantieren, dass eine Klasse nur ihren eigenen Status ändert.
Aquinas
@aquinas: Features erhalten implementiert , da sie sind nützlich , um viele oder die meisten Benutzer - nicht , weil sie vielleicht in einigen Einzelfällen nützlich sein.
Aaronaught
9

Was würde zunächst mit privaten statischen Mitgliedern geschehen? Kann nur mit statischen Methoden auf sie zugegriffen werden? Das würden Sie sicher nicht wollen, denn dann könnten Sie nicht auf Ihre consts zugreifen .

Betrachten Sie bei Ihrer expliziten Frage den Fall a StringBuilder, der als verknüpfte Liste von Instanzen von sich selbst implementiert ist:

public class StringBuilder
{
    private string chunk;
    private StringBuilder nextChunk;
}

Wenn Sie nicht auf die privaten Mitglieder anderer Instanzen Ihrer eigenen Klasse zugreifen können, müssen Sie Folgendes implementieren ToString:

public override string ToString()
{
    return chunk + nextChunk.ToString();
}

Dies wird funktionieren, aber es ist O (n ^ 2) - nicht sehr effizient. In der Tat macht das wahrscheinlich den ganzen Zweck zunichte, überhaupt eine StringBuilderKlasse zu haben. Wenn Sie auf die privaten Mitglieder anderer Instanzen Ihrer eigenen Klasse zugreifen können , können Sie dies implementieren, ToStringindem Sie eine Zeichenfolge mit der richtigen Länge erstellen und dann eine unsichere Kopie jedes Blocks an der entsprechenden Stelle in der Zeichenfolge erstellen:

public override string ToString()
{
    string ret = string.FastAllocateString(Length);
    StringBuilder next = this;

    unsafe
    {
        fixed (char *dest = ret)
            while (next != null)
            {
                fixed (char *src = next.chunk)
                    string.wstrcpy(dest, src, next.chunk.Length);
                next = next.nextChunk;
            }
    }
    return ret;
}

Diese Implementierung ist O (n), was sie sehr schnell macht und nur möglich ist, wenn Sie Zugriff auf private Mitglieder anderer Instanzen Ihrer Klasse haben .

Gabe
quelle
Ja, aber gibt es keine anderen Möglichkeiten, um dies zu umgehen, z. B. einige Felder als intern darzustellen?
MikeKulls
2
@Mike: Das Belichten eines Feldes internalmacht es weniger privat! Am Ende würden Sie die Interna Ihrer Klasse allem in ihrer Versammlung aussetzen.
Gabe
3

Dies ist in vielen Sprachen (zum Beispiel C ++) absolut legitim. Die Zugriffsmodifikatoren stammen aus dem Kapselungsprinzip in OOP. Die Idee ist, den Zugriff nach außen zu beschränken , in diesem Fall nach außen sind andere Klassen. Jede verschachtelte Klasse in C # kann beispielsweise auch auf die privaten Mitglieder ihrer Eltern zugreifen.

Dies ist zwar eine Design-Wahl für einen Sprachdesigner. Die Einschränkung dieses Zugriffs kann einige sehr häufige Szenarien extrem komplizieren, ohne viel zur Isolation von Entitäten beizutragen.

Es gibt eine ähnliche Diskussion hier

Mehran
quelle
1

Ich glaube nicht, dass es einen Grund gibt, warum wir keine weitere Datenschutzstufe hinzufügen können, bei der Daten für jede Instanz privat sind. In der Tat könnte dies sogar ein gutes Gefühl der Vollständigkeit der Sprache vermitteln.

Aber in der Praxis bezweifle ich, dass es wirklich so nützlich wäre. Wie Sie bereits betont haben, ist unsere übliche Privatität nützlich für Dinge wie Gleichheitsprüfungen sowie für die meisten anderen Operationen, an denen mehrere Instanzen eines Typs beteiligt sind. Ich mag jedoch auch Ihren Standpunkt zur Aufrechterhaltung der Datenabstraktion, da dies ein wichtiger Punkt in OOP ist.

Ich denke, die Möglichkeit, den Zugriff so einzuschränken, könnte eine nette Funktion sein, die man zu OOP hinzufügen kann. Ist es wirklich so nützlich? Ich würde nein sagen, da eine Klasse in der Lage sein sollte, ihrem eigenen Code zu vertrauen. Da diese Klasse die einzigen Dinge sind, die auf private Mitglieder zugreifen können, gibt es keinen wirklichen Grund, eine Datenabstraktion zu benötigen, wenn es sich um eine Instanz einer anderen Klasse handelt.

Natürlich können Sie Ihren Code immer so schreiben, als ob privat auf Instanzen angewendet würde. Verwenden Sie die üblichen get/setMethoden, um auf die Daten zuzugreifen / diese zu ändern. Dies würde den Code wahrscheinlich übersichtlicher machen, wenn die Klasse internen Änderungen unterliegen könnte.

Ken Wayne VanderLinde
quelle
0

Tolle Antworten oben gegeben. Ich würde hinzufügen, dass ein Teil dieses Problems die Tatsache ist, dass das Instanziieren einer Klasse in sich selbst überhaupt erst erlaubt ist. Da in einer rekursiven Logik "for" -Schleife beispielsweise diese Art von Trick verwendet wird, solange Sie über Logik verfügen, um die Rekursion zu beenden. Das Instanziieren oder Übergeben derselben Klasse in sich selbst, ohne solche Schleifen zu erzeugen, birgt jedoch logischerweise eigene Gefahren, obwohl dies ein weit verbreitetes Programmierparadigma ist. Beispielsweise kann eine C # -Klasse eine Kopie von sich selbst in ihrem Standardkonstruktor instanziieren, dies verstößt jedoch nicht gegen Regeln und erzeugt keine Kausalschleifen. Warum?

Übrigens ... das gleiche Problem gilt auch für "geschützte" Mitglieder. :((

Ich habe dieses Programmierparadigma nie vollständig akzeptiert, da es immer noch eine ganze Reihe von Problemen und Risiken mit sich bringt, die die meisten Programmierer erst dann vollständig erfassen, wenn Probleme wie dieses auftauchen und die Menschen verwirren und dem ganzen Grund für die Mitgliedschaft privater Mitglieder trotzen.

Dieser "seltsame und verrückte" Aspekt von C # ist ein weiterer Grund, warum gute Programmierung nichts mit Erfahrung und Können zu tun hat, sondern nur die Tricks und Fallen zu kennen ... wie an einem Auto zu arbeiten. Es ist das Argument, dass Regeln gebrochen werden sollten, was ein sehr schlechtes Modell für jede Computersprache ist.

Stokely
quelle
-1

Es scheint mir, dass Daten, die für andere Instanzen desselben Typs privat wären, nicht mehr unbedingt vom selben Typ wären. Es scheint sich nicht wie andere Instanzen zu verhalten oder zu verhalten. Das Verhalten kann leicht basierend auf diesen privaten internen Daten geändert werden. Das würde meiner Meinung nach nur Verwirrung stiften.

Ich persönlich denke, dass das Schreiben von Klassen, die von einer Basisklasse abgeleitet sind, ähnliche Funktionen bietet, die Sie mit "private Daten pro Instanz haben" beschreiben. Stattdessen haben Sie nur eine neue Klassendefinition pro 'eindeutigem' Typ.

C Johnson
quelle