2011-08-26 3 views
15

Quelqu'un pourrait-il m'aider à comprendre si les codes suivants sont identiques. Sinon, quelle est la différence entre l'instanciation de classe et celle d'interférence. Pour autant que je sache, Inteface n'a qu'une signature de méthode et si l'interface a été implémentée par 3 classes. Je ne sais pas trop quelle instance serait créée par la première déclaration ci-dessus.Instanciation d'interface vs instanciation de classe

Merci.

Répondre

44

Les interfaces ne peuvent pas être instanciées par définition. Vous instanciez toujours une classe concrète.

Donc dans les deux instructions votre instance est en réalité de type UnityContainer. La différence est pour la première déclaration, en ce qui concerne C#, votre container est quelque chose qui implémente IUnityContainer, qui pourrait avoir une API différente de UnityContainer.


Tenir compte:

interface IAnimal 
{ 
    void die(); 
} 

class Cat : IAnimal 
{ 
    void die() { ... } 
    void meow() { ... } 
} 

maintenant:

IAnimal anAnimal = new Cat(); 
Cat aCat= new Cat(); 

C# sait anAnimal.die() sûr des œuvres, parce que die() est défini dans IAnimal. Mais il ne vous laissera pas faire anAnimal.meow() même si c'est un Cat, alors que aCat peut invoquer les deux méthodes. Lorsque vous utilisez l'interface comme type, vous perdez en quelque sorte les informations.

Cependant, si vous aviez une autre classe Dog qui implémente également IAnimal, votre anAnimal pourrait faire référence à une instance Dog ainsi. C'est la puissance d'une interface; vous pouvez leur donner n'importe quelle classe qui l'implémente.

+4

Il existe un cas exceptionnel lorsque vous pouvez * instancier une interface: lorsqu'il s'agit d'une interface COM. – svick

+0

Nice! Je suis sûr que vos mots "perdre l'information" n'ont pas l'intention de rétrograder en utilisant des interfaces. –

+0

@Gert Essayer de le rendre facile à comprendre ... Le résultat est plus compliqué que j'avais espéré. – NullUserException

3

Il n'y a vraiment pas d'instanciation d'interface, mais il y a des variables d'interface. La première ligne est un exemple d'une telle variable.

Avec la première ligne, vous pouvez instancier container pour être n'importe quelle classe concrète qui implémente IUnityContainer. Avec la deuxième ligne, l'objet container ne pouvait être instancié qu'à partir de la classe UnityContainer ou d'une classe dérivée. Lorsque vous utilisez des variables d'interface dans votre code, cela vous permet de changer plus facilement l'implémentation concrète, ce qui rend votre code plus flexible.

+0

Ce n'est pas vraiment vrai. 'UnityContainer' implémente' IUnityContainer', donc vous pouvez passer la seconde variable aux méthodes acceptant 'IUnityContainer'. – dlev

+1

La deuxième version pourrait certainement être utilisée avec des méthodes qui prennent 'IUnityContainer' comme paramètre. Si une classe implémente une interface, elle est implicitement convertible vers cette interface. – svick

+0

Vous avez raison. J'ai mal écrit ça. Je ne sais pas ce que je pensais .... – FishBasketGordo

0

L'objet instancié et stocké dans la variable IUnityContainer container est considéré par le compilateur comme ayant uniquement les membres définis dans l'interface IUnityContainer. En d'autres termes, si la classe UnityContainer contient des membres qui ne sont pas définis par l'interface IUnityContainer, vous ne pourrez pas les appeler. D'un autre côté, vous pouvez "mettre" n'importe quel objet qui implémente l'interface IUnityContainer dans la variable IUnityContainer container - pas seulement les instances de UnityContainer. Avec la deuxième déclaration, vous êtes coincé avec des instances de UnityContainer et des objets dans sa hiérarchie d'héritage.

Consultez le C# Programming Guide to Interfaces pour plus d'informations sur les interfaces et leur utilisation.

+0

Lorsque vous avez dit "propriétés", vous vouliez probablement dire "membres". – svick

+0

Mis à jour. Merci, @svick! –

0

L'instanciation de l'interface n'est pas possible. Mais quand nous avons créé un objet pour l'interface en utilisant sa classe implémentée cela fonctionne. Supposons qu'il existe un héritage multiple, pour y parvenir, nous devons commencer par le premier.

Il n'y a pas besoin de fournir de telles choses que nous allons avec la deuxième voie. Interfaces limite l'accès direct des données et des membres de sa classe.