2009-02-12 6 views
28

En C#, quand j'ai une interface et plusieurs implémentations concrètes, est-ce que je peux lancer l'interface sur un type concret ou est-ce que le type concret est moulé pour l'interface?Cast interface à son objet de mise en œuvre concrète ou vice versa?

Quelles sont les règles dans ce cas?

+0

C#, mais je m'attends à ce que la réponse soit correcte dans tous les langages oo. – dotnetdev

+0

Ce genre de chose est susceptible d'être similaire dans tous les langages OO, mais pas nécessairement identiques. Scoping to C# afin que nous puissions vous fournir une réponse spécifique. –

Répondre

33

Les deux directions sont autorisées en Java et C#. La diffusion vers le bas nécessite une distribution explicite et peut lancer une exception si l'objet n'est pas du bon type. La prévision, cependant, n'a pas besoin de distribution explicite et est toujours sûre à faire.

qui est, en supposant que vous avez public interface Animal et deux implémentations de ce interface, Cat et Dog ....

Animal meowAnimal = new Cat(); // No cast required 
Animal barkAnimal = new Dog(); // No cast required 

Cat myCat = (Cat) meowAnimal; // Explicit cast needed 
Dog myDog = (Dog) barkAnimal; // Explicit cast needed 

Dog myPet = (Dog) meowAnimal; // Will compile but throws an Exception 

et vous aurez besoin d'un try/catch autour des moulages explicites. En C#, vous avez le mot-clé as utile:

Dog myDog = barkAnimal as Dog; 
Dog myPet = meowAnimal as Dog; 

Aucune exception sera levée, et monChien serez et non nulle mypet sera nulle. Java n'a pas de mot-clé équivalent bien que vous puissiez toujours utiliser les tests if (meowAnimal instanceof Dog) pour conserver la sécurité du type. (Je suppose que le mot-clé « as » génère bytecode qui fait le cas, l'attribution nulle de l'is échoue. Mais peut-être .NET a une instruction de bytecode qui fait l'équivalent de « as ».)

+1

Qu'en est-il de "is": if (meowAnimal is Dog) {Chien d = (Dog) meowAnimal} –

+0

Vous pouvez également utiliser le mot-clé "is" pour éviter de lancer des exceptions. – Eddie

+8

faire un cast 'as' et une vérification nulle est préférable à une vérification 'is' et une distribution explicite comme vous finissez par lancer deux fois, une fois pour le qui retourne vrai ou faux, puis une fois pour la distribution explicite ((Chien)) animal). –

0

Les deux sont valides, étant donné qu'il s'agit d'une distribution logique. Plusieurs fois, les consommateurs de votre interface n'ont pas accès aux classes concrètes, ce qui est une raison majeure pour avoir une interface en premier lieu.

3

Si vous parlez de Java (mais les règles pour les autres langues sont similaires), il est comme ceci:

Vous pouvez (vers le bas) lancer une interface à une mise en œuvre concrète, ssi la référence que vous lancez est en fait une référence à la mise en œuvre concrète spécifique. Cela signifie

Vehicle v=new Car(); 
(Car)v // this is OK 
(Bus)v // this is not 

L'erreur se manifeste comme ClassCastException en Java.

Vous pouvez librement convertir une implémentation concrète d'une interface vers l'interface.

+0

J'ai défini la question d'origine sur C#, donc votre réponse n'est plus pertinente. Pardon. –

13

Dans la plupart des langues, vous pouvez diffuser les deux directions. Si vous avez une classe concrète, vous pouvez la convertir en interface. Si vous avez une interface, il est possible de lancer vers la classe concrète.

Généralement, vous voulez seulement aller dans la première direction. La raison en est que vous ne devriez pas savoir ce qu'est la classe concrète quand vous avez seulement un pointeur vers l'interface. Si vous passez quelque chose en tant qu'interface, vous devriez être capable de faire tout ce dont vous avez besoin à partir de cette interface. Si vous avez besoin d'utiliser des parties de l'objet concret qui ne sont pas sur l'interface, vous avez un problème de conception qui devrait être résolu au lieu de lancer.

+0

Qu'en est-il de WPF? Que se passe-t-il si je récupère des interfaces à partir d'un service et que j'ai besoin de les convertir ViewModels pour lier une interface utilisateur WPF? – Darkonekt

0

Une interface peut être la classe entière, si toutefois ne doit pas être être, il est préférable quand vous créez un constructeur qui accepte l'interface comme paramètre et copiez les paramètres, de cette façon vous avez le contrôle sur ce qui se passe et ce qui est nécessaire.

Questions connexes