Certains ont suggéré que les choses peuvent devenir incontrôlables en utilisant un ami. Je serais d'accord, mais cela n'en diminue pas l'utilité. Je ne suis pas certain que cet ami blesse nécessairement le paradigme OO pas plus que de rendre publics tous les membres de votre classe. Certes, le langage vous permettra de rendre tous vos membres publics, mais c'est un programmeur discipliné qui évite ce type de modèle de conception. De même, un programmeur discipliné réserverait l'utilisation d'un ami pour des cas spécifiques où cela a du sens. Je sens que l'intérieur expose trop dans certains cas. Pourquoi exposer une classe ou une méthode à tout dans l'assembly?
J'ai une page ASP.NET qui hérite de ma propre page de base, qui à son tour hérite de System.Web.UI.Page. Dans cette page, j'ai du code qui gère les rapports d'erreur de l'utilisateur final pour l'application dans une méthode protégée
ReportError("Uh Oh!");
Maintenant, j'ai un contrôle utilisateur qui est contenu dans la page. Je veux que le contrôle utilisateur puisse appeler les méthodes de rapport d'erreur dans la page.
MyBasePage bp = Page as MyBasePage;
bp.ReportError("Uh Oh");
Il ne peut pas faire cela si la méthode ReportError est protégée. Je peux le rendre interne, mais il est exposé à n'importe quel code de l'assembly. Je veux juste qu'il soit exposé aux éléments de l'interface utilisateur qui font partie de la page actuelle (y compris les contrôles enfants). Plus précisément, je veux que ma classe de contrôle de base définisse exactement les mêmes méthodes de rapport d'erreurs et appelle simplement des méthodes dans la page de base.
protected void ReportError(string str) {
MyBasePage bp = Page as MyBasePage;
bp.ReportError(str);
}
Je pense que quelque chose comme friend pourrait être utile et implémenté dans le langage sans rendre le langage moins "OO" comme, peut-être en tant qu'attributs, afin que vous puissiez avoir des classes ou des méthodes amis de classes ou de méthodes spécifiques, permettant au développeur de fournir très accès spécifique. Peut-être quelque chose comme ... (pseudo code)
[Friend(B)]
class A {
AMethod() { }
[Friend(C)]
ACMethod() { }
}
class B {
BMethod() { A.AMethod() }
}
class C {
CMethod() { A.ACMethod() }
}
Dans le cas de mon exemple précédent, j'ai peut-être quelque chose comme ce qui suit (on peut discuter de la sémantique, mais j'essaie juste de faire passer l'idée):
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);
}
}
À mon avis, le concept d'ami n'a pas plus de risque que de rendre les choses publiques ou de créer des méthodes ou des propriétés publiques pour accéder aux membres. Si quelque chose d'ami permet un autre niveau de granularité dans l'accessibilité des données et vous permet de restreindre cette accessibilité plutôt que de l'élargir avec interne ou public.