OVH Cloud OVH Cloud

Comment masquer une interface en C# ?

12 réponses
Avatar
Laurent Vigne
Bonjour , je voudrais savoir comment faire pour rendre les méthodes d'une
interface inaccessibles de l'extérieur. En C++ il est possible lorsqu'on
dérive de spécifier une visibilité. En C# cela est impossible, normal
puisque l'on peut dériver d'une seule classe et que l'on doit toujours avoir
accès à la classe Object de base. Cependant lorsque l'on souhaite
implémenter une interface je ne comprend pas pourquoi on ne peut pas
implémenter les méthodes avec une visibilité réduite !



----------------------------------------------------------------------------
-------------------------------------

Exemple :



internal Interface ImyInterface // Ici "internal" permet de ne pas
montrer mon interface de l'exterieur, parfait !!!

{

void MafonctionTresPrivee(); // Impossible de mettre un private ou
internal ici, c plutôt normal

}



public class A, ImyInterface // Impossible de mettre un private ou
internal en implementant l'interface ici, c'est la logique du C#, Ok
j'accepte

{

public void MafonctionTresPrivee() // impossible de mettre la
surcharge en private ou internal !!! Erreur de compilateur ?

{

ASSERT(false);

}

}



public class B

{

A myObjectA = new A();

myObjectA .MafonctionTresPrivee(); // Et voila on peut accéder à ma
fonction !!!

}

----------------------------------------------------------------------------
------------------------------------




Bien sur il existe des bidouilles pour pouvoir masquer ces méthodes, comme
implémenter une 3eme classe.

Mais j'aimerais qqc de propre !



Merci d'avance

10 réponses

1 2
Avatar
Paul Bacelar
Là, je ne suit pas. Une Interface est un contrat d'utilisation, c'est du
tout ou rien.

Regarde du côté du modificateur "new", mais, franchement, je pense que vous
faite fausse route.
--
Paul Bacelar


"Laurent Vigne" wrote in message
news:cl0jvv$tvi$
Bonjour , je voudrais savoir comment faire pour rendre les méthodes d'une
interface inaccessibles de l'extérieur. En C++ il est possible lorsqu'on
dérive de spécifier une visibilité. En C# cela est impossible, normal
puisque l'on peut dériver d'une seule classe et que l'on doit toujours


avoir
accès à la classe Object de base. Cependant lorsque l'on souhaite
implémenter une interface je ne comprend pas pourquoi on ne peut pas
implémenter les méthodes avec une visibilité réduite !



--------------------------------------------------------------------------


--
-------------------------------------

Exemple :



internal Interface ImyInterface // Ici "internal" permet de ne pas
montrer mon interface de l'exterieur, parfait !!!

{

void MafonctionTresPrivee(); // Impossible de mettre un private ou
internal ici, c plutôt normal

}



public class A, ImyInterface // Impossible de mettre un private


ou
internal en implementant l'interface ici, c'est la logique du C#, Ok
j'accepte

{

public void MafonctionTresPrivee() // impossible de mettre la
surcharge en private ou internal !!! Erreur de compilateur ?

{

ASSERT(false);

}

}



public class B

{

A myObjectA = new A();

myObjectA .MafonctionTresPrivee(); // Et voila on peut accéder à


ma
fonction !!!

}

--------------------------------------------------------------------------


--
------------------------------------




Bien sur il existe des bidouilles pour pouvoir masquer ces méthodes, comme
implémenter une 3eme classe.

Mais j'aimerais qqc de propre !



Merci d'avance






Avatar
Patrick Philippot
Laurent Vigne wrote:
Mais j'aimerais qqc de propre !



Bonjour,

C'est déjà propre :-) . Paul a raison: vous mélangez héritage
d'interface et héritage d'implémentation.

A partir du moment où l'on déclare qu'une classe supporte une interface
particulière, non seulement on s'engage sur un contrat pour cette classe
et ses dérivées mais on met en oeuvre pour les clients un mécanisme de
polymorphisme. Ce que vous voulez faire, c'est le plus sûr moyen
d'empêcher le polymorphisme de fonctionner. Côté client, le code
appelant doit pouvoir être sûr qu'ayant une référence sur un objet de
type ImyInterface ou sur une dérivée d'une telle classe, il peut appeler
toute méthode de ImyInterface. C'est la base *fondamentale et
intangible* du polymorphisme. Or vous voulez casser cette mécanique. Pas
étonnant qu'on ne vous y aide pas... :-)

--
Patrick Philippot - Microsoft MVP
MainSoft Consulting Services
www.mainsoft.fr
Avatar
Laurent Vigne
Non, je ne mélange pas du tout et ce n'est pas une erreur de modélisation /
Conception. Mon interface est bien déclarée en internal, et cela est voulu.
Les assembly externes ont ainsi aucune connaissance de cette interface et ne
peuvent donc pratiquer de polymorphisme.

Le probleme se pose sur l'implémentation des méthodes de cette interface qui
doivent être forcément public et donc être vu voir même être appelées par
les assembly externes. Ce que je ne souhaite pas du tout.

J'ai demandé en parallèle sur le forum US, ou l'on m'a proposé cette
solution, j'essaierai ce soir :)

---------------------------------------------------
internal interface MyInterface {
void DoSomething();
}

public class MyClass : MyInterface {
public MyClass() {
}

void MyInterface.DoSomething() {
}
}


---------------------------------------------------

Merci pour vos réponses !


"Patrick Philippot" wrote in message
news:
Laurent Vigne wrote:
> Mais j'aimerais qqc de propre !

Bonjour,

C'est déjà propre :-) . Paul a raison: vous mélangez héritage
d'interface et héritage d'implémentation.

A partir du moment où l'on déclare qu'une classe supporte une interface
particulière, non seulement on s'engage sur un contrat pour cette classe
et ses dérivées mais on met en oeuvre pour les clients un mécanisme de
polymorphisme. Ce que vous voulez faire, c'est le plus sûr moyen
d'empêcher le polymorphisme de fonctionner. Côté client, le code
appelant doit pouvoir être sûr qu'ayant une référence sur un objet de
type ImyInterface ou sur une dérivée d'une telle classe, il peut appeler
toute méthode de ImyInterface. C'est la base *fondamentale et
intangible* du polymorphisme. Or vous voulez casser cette mécanique. Pas
étonnant qu'on ne vous y aide pas... :-)

--
Patrick Philippot - Microsoft MVP
MainSoft Consulting Services
www.mainsoft.fr




Avatar
Patrick Philippot
Laurent Vigne wrote:
Non, je ne mélange pas du tout et ce n'est pas une erreur de
modélisation / Conception. Mon interface est bien déclarée en
internal, et cela est voulu. Les assembly externes ont ainsi aucune
connaissance de cette interface et ne peuvent donc pratiquer de
polymorphisme.



A ce moment là, pourquoi ne pas faire de l'aggrégation ou du
containment? Au lieu d'avoir une classe qui dérive de ImyInterface,
implémentez une propriété privée qui est un objet appartenant à une
classe qui implémente ImyInterface et déléguez les appels à cet objet
quand c'est nécessaire.

--
Patrick Philippot - Microsoft MVP
MainSoft Consulting Services
www.mainsoft.fr
Avatar
Laurent Vigne
Car j'ai un systeme de polymorphisme interne :
D'une manière très simplifié cela donne :

---------------------------------------------------

Mon interface I est interne à l'assembly.

Ma classe A est public et implemente l'interface I
Ma classe B est public et implemente l'interface I
Ma classe C est public et implemente l'interface I

Ma classe X est interne et appelle les méthodes de l'interface I sans
connaitre la classe A / B ou C sur lequel elle travaille.

---------------------------------------------------

Pour l'instant j'ai fais une bidouille pas vraiment jolie :

Ma classe A est public
Ma classe B est public
Ma classe C est public

Les classes A, B et C implémentent les même méthodes que l'interface mais
déclarées en internal

Ma classe Ax est internal, connais la classe A et implemente l'interface I
Ma classe Bx est internal, connais la classe B et implemente l'interface I
Ma classe Cx est internal, connais la classe C et implemente l'interface I

Ma classe X est internal et appelle les méthodes de l'interface I sans
connaitre la classe Ax / Bx ou Cx sur lequel elle travaille.

Les classes Ax Bx et Cx font juste une redirection en appellant les methodes
similaires des classes A B et C

-------------------------------------------------------

"Patrick Philippot" wrote in message
news:%
Laurent Vigne wrote:
> Non, je ne mélange pas du tout et ce n'est pas une erreur de
> modélisation / Conception. Mon interface est bien déclarée en
> internal, et cela est voulu. Les assembly externes ont ainsi aucune
> connaissance de cette interface et ne peuvent donc pratiquer de
> polymorphisme.

A ce moment là, pourquoi ne pas faire de l'aggrégation ou du
containment? Au lieu d'avoir une classe qui dérive de ImyInterface,
implémentez une propriété privée qui est un objet appartenant à une
classe qui implémente ImyInterface et déléguez les appels à cet objet
quand c'est nécessaire.

--
Patrick Philippot - Microsoft MVP
MainSoft Consulting Services
www.mainsoft.fr




Avatar
Zazar
Bonsoir,

A partir du moment où l'on déclare qu'une classe supporte une interface
particulière, non seulement on s'engage sur un contrat pour cette classe
et ses dérivées mais on met en oeuvre pour les clients un mécanisme de
polymorphisme. Ce que vous voulez faire, c'est le plus sûr moyen
d'empêcher le polymorphisme de fonctionner. Côté client, le code
appelant doit pouvoir être sûr qu'ayant une référence sur un objet de
type ImyInterface ou sur une dérivée d'une telle classe, il peut appeler
toute méthode de ImyInterface. C'est la base *fondamentale et
intangible* du polymorphisme. Or vous voulez casser cette mécanique. Pas
étonnant qu'on ne vous y aide pas... :-)



Je pense que l'OP soulève le problème suivant : on ne peut pas déclarer une
interface internal exposant des méthodes de type internal.
J'ai déjà été confronté à cette situation et je n'ai pas non plus compris
pourquoi cette interdiction.

--
Zazar
Avatar
Ambassadeur Kosh
pour completer la réponse de Paul, je vais la jouer cours de morale :

le principe qui consiste à dire "comment fait on en C# ce qu'on faisait en
C++" ne fait pas avancer les choses, ni pour vous, ni pour l'appli.
C++ offrait des possibilités qui favorisaient l'implantation au detriment de
la conception. hors, il se trouve qu'une "bonne" conception conduit souvent
à des perfs tout aussi bonnes, voire meilleures.
en clair, l'heritage protected et private, ça sert à nib, l'heritage
multiple d'implantation, c'est franchement pas la panacée.

l'idée, on ne le repetera jamais assez, c'est l'utilisation.

class A { public f() {...} }

class B : private A
{
public g() { A::f() ; }
}

va devenir

class B : object
{
public g() { detail.f() ; }
private A detail = new A() ;
}

ce qui permet de dériver A à volonté, en fournissant plusieurs f possibles
selon le cas, et de rendre A abstraite. autrement plus interessant non ?
jetter un oeil sur System.IO. l'idée des Writer et Reader est un exemple de
concret. suffit de se souvenir de <iostream.h> pour comprendre la
superiorité du concept.
la transition n'est pas facile ou évidente (je l'ai faite), mais il y'a au
bout un bénéfice immense.

voila voila
Avatar
Laurent Vigne
Voila j'ai pu tester le code suivant hier soir :

(Viens du post de Robert Jordan sur le forum US)

-----------------------------------------------
internal interface MyInterface {
void DoSomething();
}

public class MyClass : MyInterface {
public MyClass() {
}

void MyInterface.DoSomething() {
}
}


-----------------------------------------------

Cela résoud entierement mon probleme !!!!

La méthode DoSomething() implémentée de cette manière n'est pas accessible
directement à partir de MyClass.
Et comme l'interface est déclarée en internal, il n'y a ainsi aucune
visibilité sur DoSomething() à l'exterieur de l'assembly, même si MyClass
est public !



"Laurent Vigne" wrote in message
news:cl0jvv$tvi$
Bonjour , je voudrais savoir comment faire pour rendre les méthodes d'une
interface inaccessibles de l'extérieur. En C++ il est possible lorsqu'on
dérive de spécifier une visibilité. En C# cela est impossible, normal
puisque l'on peut dériver d'une seule classe et que l'on doit toujours


avoir
accès à la classe Object de base. Cependant lorsque l'on souhaite
implémenter une interface je ne comprend pas pourquoi on ne peut pas
implémenter les méthodes avec une visibilité réduite !



--------------------------------------------------------------------------


--
-------------------------------------

Exemple :



internal Interface ImyInterface // Ici "internal" permet de ne pas
montrer mon interface de l'exterieur, parfait !!!

{

void MafonctionTresPrivee(); // Impossible de mettre un private ou
internal ici, c plutôt normal

}



public class A, ImyInterface // Impossible de mettre un private


ou
internal en implementant l'interface ici, c'est la logique du C#, Ok
j'accepte

{

public void MafonctionTresPrivee() // impossible de mettre la
surcharge en private ou internal !!! Erreur de compilateur ?

{

ASSERT(false);

}

}



public class B

{

A myObjectA = new A();

myObjectA .MafonctionTresPrivee(); // Et voila on peut accéder à


ma
fonction !!!

}

--------------------------------------------------------------------------


--
------------------------------------




Bien sur il existe des bidouilles pour pouvoir masquer ces méthodes, comme
implémenter une 3eme classe.

Mais j'aimerais qqc de propre !



Merci d'avance






Avatar
Laurent Vigne
Transformer les héritages en agrégation, c'est se donner une grosse
limitation de la modélisation objet ! Et cela ne résout pas du tout mon
problème exposé !

Il est tout à fait compréhensible en C# de ne pas pouvoir dériver avec une
visibilité réduite (comme en C++) car cela masquerait la classe "object" de
base (en C#, toutes les classes dérivent de object, et il est indispensable
d'avoir une visibilité sur cette classe quelque soit l'implémentation).

Cependant il n'était pas du tout logique d'exposer de façon public les
méthodes qui implémentent une interface (surtout si celle-ci est déclarée
internal). Voir la solution du problème dans mon post plus bas.


"Ambassadeur Kosh" wrote in message
news:%
pour completer la réponse de Paul, je vais la jouer cours de morale :

le principe qui consiste à dire "comment fait on en C# ce qu'on faisait en
C++" ne fait pas avancer les choses, ni pour vous, ni pour l'appli.
C++ offrait des possibilités qui favorisaient l'implantation au detriment


de
la conception. hors, il se trouve qu'une "bonne" conception conduit


souvent
à des perfs tout aussi bonnes, voire meilleures.
en clair, l'heritage protected et private, ça sert à nib, l'heritage
multiple d'implantation, c'est franchement pas la panacée.

l'idée, on ne le repetera jamais assez, c'est l'utilisation.

class A { public f() {...} }

class B : private A
{
public g() { A::f() ; }
}

va devenir

class B : object
{
public g() { detail.f() ; }
private A detail = new A() ;
}

ce qui permet de dériver A à volonté, en fournissant plusieurs f possibles
selon le cas, et de rendre A abstraite. autrement plus interessant non ?
jetter un oeil sur System.IO. l'idée des Writer et Reader est un exemple


de
concret. suffit de se souvenir de <iostream.h> pour comprendre la
superiorité du concept.
la transition n'est pas facile ou évidente (je l'ai faite), mais il y'a au
bout un bénéfice immense.

voila voila




Avatar
Ambassadeur Kosh
> Transformer les héritages en agrégation, c'est se donner une grosse
limitation de la modélisation objet ! Et cela ne résout pas du tout mon
problème exposé !



ben non jsutement.

http://www.dotnetguru.org/articles/dossiers/heritageimpl/FragileBaseClass.htm

on va pas repartir sur ce genre de débats. les gars qui viennent de C++ ont
du mal de se debarasser de cette idée que l'heritage d'implantation est un
benefice.

Cependant il n'était pas du tout logique d'exposer de façon public les
méthodes qui implémentent une interface (surtout si celle-ci est déclarée
internal). Voir la solution du problème dans mon post plus bas.



des méthodes protected passent encore, mais franchement, c'est trop pour de
l'implantation.
vu que ça ne regarde pas l'exterieur, ça a plus sa place dans une classe
abstraite que dans une interface.

et c'est le cas d'ailleurs.

enfin bon, ce que j'en dis moi...
1 2