2012-05-02 25 views
9

Espero que alguien aquí me explique las suposiciones incorrectas que estoy haciendo. En C# 4.0, tengo 2 interfaces y una clase que implementa ambas. En un método declaro una variable con el tipo de la primera interfaz, instanciarlo utilizando la clase que implementa las interfaces y de alguna manera puede lanzar con éxito a la segunda interfaz como en el siguiente código:Lanzando una interfaz a otra interfaz que no hereda

public interface IFirstInterface 
    { 
     void Method1(); 
    } 

    public interface ISecondInterface 
    { 
     void Method2(); 
    } 

    public class InterfaceImplementation : IFirstInterface, ISecondInterface 
    { 
     public void Method1() { } 
     public void Method2() { } 
    } 

    public class SomeClass 
    { 
     public void SomeMethod() 
     { 
      IFirstInterface first = new InterfaceImplementation(); 
      first.Method1(); 

      // Shouldn't the next line return null? 
      ISecondInterface second = first as ISecondInterface; 
      // second is not null and the call to Method2() works fine 
      second.Method2(); 
     } 
    } 

estoy tratando de entender por qué el casting es exitoso. Sí, la clase implementa ambas interfaces, pero creo que dado que la primera variable se declara como IFirstInterface (que no hereda de ISecondInterface), la conversión todavía no se ha realizado.

También he intentado reestructurar mi código de otras maneras, como no usar 'como', pero el lanzamiento sigue siendo exitoso.

¿Qué me estoy perdiendo?

Respuesta

7

Según su ejemplo, debe probar el tipo de letra antes de llamar a cualquiera de las funciones. La primera creación creará una "Implementación de interfaz" completamente calificada que admite ambas interfaces. Sin embargo, lo está colocando en un tipo declarado de solo la primera interfaz. Entonces, desde la perspectiva del "primer" objeto, solo se preocupa por cualquier cosa asociada como una implementación de IFirstInterface.

Ahora, en segundo lugar ... Aunque hayas creado el objeto, aún puedes preguntar ... Por cierto ... ¿también eres una Segunda Interfaz? Si es así, haga esto ...

IFirstInterface first = new InterfaceImplementation(); 

if(first is ISecondInterface) 
    // typecast since the second interface is legit, then call it's method 2 
    ((ISecondInterface)first).Method2(); 
+0

Esto confirma lo que pensé que estaba pasando. Gracias –

+0

Muchas gracias, realmente lo necesitaba. +1 (+10 si pudiera). – Arjang

0

Si mira desde el punto de vista del objeto concreto, puede decir "Soy un IFirstInterface, pero también soy un ISecondInterface". ¿Es eso lo que quieres decir? La pregunta que describiste terminaría en el molde dentro de una cadena de herencia/implementación.

1

Lo único que te falta es que así es exactamente como debe ser, y esa es una característica útil, no es un problema. Cuando se lanza, puede pensar que el código básicamente dice: "No me importa lo que yo sabía que era el tipo de este objeto, quiero ver si se puede convertir a tipo T". En este caso, dado que el objeto subyacente es del tipo InterfaceImplementation, independientemente del hecho de que actualmente se conoce como IFirstInterface, la respuesta es que sí, se puede convertir a ISecondInterface.

0

Bienvenido a polimorfismo. El objeto first siempre será una instancia de InterfaceImplementation. Cómo elige hacer referencia a él no afecta lo que el objeto realmente "es". Así es como funciona el concepto de abstracción como un todo.

3

El tipo real de la instancia first apunta a implementar ambas interfaces. Así que obviamente ambos Method1 y Method2 están disponibles en el objeto.

El tipo estático de first sólo se le permite acceder a Method1. El tipo estático de second solo le permite acceder al Method2. Si declara una referencia al objeto usando cualquiera de las interfaces, solo selecciona ver la instancia como un objeto que cumple el contrato seleccionado (la interfaz).

Como InterfaceImplementation implementa ambas interfaces, tiene la opción de referirse a la instancia utilizando cualquiera de las interfaces.

Cuestiones relacionadas