Einige haben vorgeschlagen, dass die Dinge durch die Verwendung von Freunden außer Kontrolle geraten können. Ich würde zustimmen, aber das mindert nicht seine Nützlichkeit. Ich bin mir nicht sicher, ob ein Freund das OO-Paradigma notwendigerweise mehr verletzt, als alle Ihre Klassenmitglieder öffentlich zu machen. Sicherlich erlaubt Ihnen die Sprache, alle Ihre Mitglieder öffentlich zu machen, aber es ist ein disziplinierter Programmierer, der diese Art von Entwurfsmuster vermeidet. Ebenso würde ein disziplinierter Programmierer die Verwendung von Freunden für bestimmte Fälle reservieren, in denen dies sinnvoll ist. Ich fühle, dass interne Belichtungen in einigen Fällen zu viel sind. Warum sollte eine Klasse oder Methode für alles in der Assembly verfügbar gemacht werden?
Ich habe eine ASP.NET-Seite, die meine eigene Basisseite erbt, die wiederum System.Web.UI.Page erbt. Auf dieser Seite habe ich Code, der die Fehlerberichterstattung für Endbenutzer für die Anwendung in einer geschützten Methode behandelt
ReportError("Uh Oh!");
Jetzt habe ich ein Benutzersteuerelement, das auf der Seite enthalten ist. Ich möchte, dass das Benutzersteuerelement die Fehlerberichterstattungsmethoden auf der Seite aufrufen kann.
MyBasePage bp = Page as MyBasePage;
bp.ReportError("Uh Oh");
Dies ist nicht möglich, wenn die ReportError-Methode geschützt ist. Ich kann es intern machen, aber es ist jedem Code in der Assembly ausgesetzt. Ich möchte nur, dass es den UI-Elementen angezeigt wird, die Teil der aktuellen Seite sind (einschließlich untergeordneter Steuerelemente). Insbesondere möchte ich, dass meine Basissteuerungsklasse genau dieselben Fehlerberichtsmethoden definiert und einfach Methoden auf der Basisseite aufruft.
protected void ReportError(string str) {
MyBasePage bp = Page as MyBasePage;
bp.ReportError(str);
}
Ich glaube, dass so etwas wie "Freund" nützlich und in der Sprache implementiert sein könnte, ohne die Sprache weniger "OO" zu machen, vielleicht als Attribute, so dass Klassen oder Methoden Freunde bestimmter Klassen oder Methoden sein können, so dass der Entwickler sehr viel bereitstellen kann spezifischer Zugang. Vielleicht so etwas wie ... (Pseudocode)
[Friend(B)]
class A {
AMethod() { }
[Friend(C)]
ACMethod() { }
}
class B {
BMethod() { A.AMethod() }
}
class C {
CMethod() { A.ACMethod() }
}
Im Fall meines vorherigen Beispiels haben Sie vielleicht etwas wie das Folgende (man kann die Semantik argumentieren, aber ich versuche nur, die Idee zu vermitteln):
class BasePage {
[Friend(BaseControl.ReportError(string)]
protected void ReportError(string str) { }
}
class BaseControl {
protected void ReportError(string str) {
MyBasePage bp = Page as MyBasePage;
bp.ReportError(str);
}
}
Aus meiner Sicht besteht für das Freund-Konzept kein größeres Risiko, als Dinge öffentlich zu machen oder öffentliche Methoden oder Eigenschaften für den Zugriff auf Mitglieder zu erstellen. Wenn überhaupt, erlaubt ein Freund ein anderes Maß an Granularität bei der Zugänglichkeit von Daten und ermöglicht es Ihnen, diese Zugänglichkeit einzugrenzen, anstatt sie mit internen oder öffentlichen zu erweitern.