9
votes

Pourquoi une fonction avec un modificateur protégé peut être remplacée et accessible à chaque fois?

Je suis C # Programmer Nouveauté de la langue D. Je suis un peu confondant avec le langage de programmation D.

supposant que j'ai la classe suivante: xxx

modificateur signifie que je peux accéder à la méthode .foo () sur la classe héritée, alors pourquoi ce programme d compile normalement?

Voici l'équivalent à c # .NET : xxx

Il ne compile pas et donné le message d'erreur suivant (comme prévu):

Test.cs (10,30): Erreur CS0507: B.FOO () ': impossible de changer d'accès modificateurs lors du remplacement de protégé «membre hérité» `a.fooo () '

Quelqu'un peut-il expliquer ce comportement en D? Merci d'avance.


6 commentaires

Pourquoi es-tu confus? C # et D ne sont que des langues différentes, alors ils font les choses différemment. Au premier aspect, les deux approches ont un sens pour moi, alors il appartient aux concepteurs de la langue de décider de la voie à suivre.


Humm, parce que j'avais à l'esprit que les modificateurs d'accès d'un langage de programmation orienté objet fonctionnant de la même manière.


Des bowvotes - peuvent expliquer s'il vous plaît?


Et vous pouvez faire l'inverse en C #, voir msdn.microsoft.com/en-us/library/aa288461%28v=vs.71%29.aspx ; c'est-à-dire public / protégé à privé. interface i {void foo (); } Classe A {Vidual Public Void Foo () {}} Classe B: A, I {void i.foo () {}}


@Jack, ils ne fonctionnent certainement pas de la même manière. Par exemple, C ++ n'a pas interne et c # n'a pas ami . Ou Python, cela n'a pas du tout de modificateurs d'accès. Il n'y a pas de norme sur ce que les modificateurs d'accès devraient avoir une langue orientée objet. Chaque langue est simplement différente.


C # a beaucoup de restrictions destinées à réduire les erreurs. "Parce que j'avais à l'esprit que les modificateurs d'accès d'un langage de programmation orienté objet fonctionnant de la même manière" - qui ne répond pas à la question. Pourquoi avez-vous eu cela à l'esprit? Il n'y a aucune base rationnelle pour une telle croyance.


3 Réponses :


19
votes

Il n'y a pas de but dans la prévention du remplacement. La classe dérivée pourrait implémenter une fonction de transfert triviale permettant d'accéder. Envisagez:

public class A {
    protected void foo() {
        writefln("A.foo() called.");
    }
};

public class B : A {
   protected override void foo() { // OK
       writefln("B.foo() called.");
   }
   public void call_foo() {
       foo(); // But I allowed public access anyway!
   }
};


5 commentaires

Humm, alors c'est d designer. Dans la langue C # .NET , il n'est pas possible d'écrire quelque chose comme le call_foo () méthode. Il a donné une erreur CS0122: A.FOO () 'est inaccessible en raison de son niveau de protection. Merci pour votre réponse. :)


@Jack: Quoi, en C #, vous ne pouvez pas écrire une méthode publique qui appelle une méthode protégée?


Non, ne fonctionne pas pour moi, j'ai testé sur C # -Mono et cela compte tenu du message d'erreur ci-dessus.


@Jack: C'est parce que vous avez appelé a.foo () directement dans votre exemple d'origine. Jetez un coup d'œil à Ceci , semble fonctionner correctement.


@Puppy Vous devez ajouter un mot-clé virtuel, vérifiez l'exemple de votre lien. Virtual vous permet de remplacer la méthode



7
votes

Le comportement d'un des matchs dans ce comportement de Java. Une classe dérivée peut donner à sa fonction un niveau d'accès moins restrictif que celui sur la fonction de la classe de base, mais pas un qui est plus restrictif. Donc, une fonction de peut être remplacée par rapport à protégé ou public , mais il ne peut pas être remplacé par privé , et un fonction publique ne peut être remplacé que par public .

Je ne sais pas pourquoi c # limiterait protégé tel que vous ne pouviez pas le remplacer par une fonction . Comme quelqu'un qui a programmé une grande affaire en C ++, D et Java, mais très peu en C #, le choix de C # ici fait très peu de sens pour moi. C ++, D et Java l'autorisent tous.


0 commentaires

8
votes

Parce qu'il y a de grandes réponses à la question "Pourquoi c'est possible?" Je pense que c # mérite des explications pourquoi ce n'est pas possible: il s'agit de la "philosophie" d'une conception linguistique et peut être bouillie à "IS-A" VS "a-un" affrontement d'idées.

C ++ est tout à propos de la pensée "A-A-A", dont certaines ont été transmises à D et Java. B a méthode FOO et ceci est le plus important pour le compilateur et le programmeur - pas ce que B est. En C ++, il est même possible de redéclaré une méthode comme privée (ou hérite de classe comme privée) qui signifie qu'un membre d'une volonté ne sera pas exposé par b.

c # est hardcore sur le concept "is-a". Par conséquent, parce que c'est en fait est A, tout en B doit être comme dans A. ni le compilateur ni le programmeur ne doivent s'inquiéter des changements, car aucun changement n'est possible. B est toujours un remplaçant de goutte parfait pour A.

La philosophie "Is-a" interdit le programme C # de publication du membre précédemment protégé, même s'il est trivial de le faire via une emballage publique. Cela a peu de sens et n'est qu'un petit inconvénient ici - mais c'est une grosse affaire de garder la philosophie de langue cohérente.


0 commentaires