entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

2votos

Buenas, leyendo la documentación de la interfaz IEnumerable me encuentro con que en el código de ejemplo se hace esto:

// Implementation for the GetEnumerator method.
IEnumerator IEnumerable.GetEnumerator()
{
   return (IEnumerator) GetEnumerator();
}

public PeopleEnum GetEnumerator()
{
    return new PeopleEnum(_people);
}

Entiendo básicamente los usos de la implementación explicita de una interfaz (múltiples interfaces con el mismo nombre de método, ocultamiento de métodos, etc), lo que no comprendo es con qué fin se hace una EII si dentro de ésta se llama al método implícito, como lo veo diría que es redundante. He encontrado unas líneas parecidas en el libro Pro ASP.NET MVC 5.

namespace LanguageFeatures.Models {
    public class ShoppingCart : IEnumerable<Product> {
        public List<Product> Products { get; set; }
        public IEnumerator<Product> GetEnumerator() {
            return Products.GetEnumerator();
        }
        IEnumerator IEnumerable.GetEnumerator() {
            return GetEnumerator();
        }
    }
}

No sé si sea algo propio del uso en conjunto de estas interfaces, pero no he podido encontrar más ejemplos. Tal vez sea solo una práctica o me estoy saltando algo.
¡Gracias!

1 Respuesta

0voto

Leonardo-Tadei Puntos227320

Hola votagus,

Primero, aclararte que jamás escribí una línea de código en C#. Me animo a responderte porque hay involucrado un principio de la POO de por medio, y de eso sí entiendo bastante.

El uso de interfaces es un mecanismo más ligero que la herencia para definir protocolo y más flexible porque una clase pude implementar varias interfaces.

Dado que la interfaz solo define un protocolo, será tarea de la clase implementar el iterador como mejor le parezca a cada uno, siempre yu cuando por supuesto se implemente toda la interfaz declarada.

Es por esto que el iterador puede ser implementado luego con cualquier estructura que se pueda recorrer: vectores, listas, colecciones o incluso cosas más esotéricas como archivos en el disco, mensajes en la bandeja de GMail y un largo etc. Es decir, hay que implementar en la clase alguna estructura que implemente el iterador concreto.

Se mantiene así la idea de la POO de ocultación de la información: la cosa funciona independientemente de cómo se haya implementado el enumerador.

En el primer ejemplo es un PeopleEnum(), en el segundo es una lista List<Product> Products . Los ejemplos devuelven en getEnumerator() el iterador correspondiente.

Posiblemente tu confusión venga porque existe un "iterador" ya implementado en el framework que ya implemente internamente a la clase, y estés confundiendo a esta clase con la interfaz que implementa.

Espero haberte orientado un poco!

0voto

votagus comentado

Gracias por la respuesta, lo que dices es muy interesante, pero no es la duda que tengo. Justamente menciono que los ejemplos que encontré son de la clase IEnumerable porque no sé si eso implica algo o sea solo una coincidencia.
En C# (no sé en qué otros lenguajes) puedes implementar los métodos de forma implícita usando el modificador public dentro de la clase que lo implementa:

public int metodo () {}

o bien una implementación explícita, escribiendo antes del método el nombre de la interfaz:

int Interfaz.metodo () {}

Con implementar de la primera forma el método es accesible desde una instancia de la clase y la interfaz, cosa que no pasa si solo se implementa de la segunda forma, en cuyo caso solo es accesible desde la interfaz (via cast).
Ahora, lo que no comprendo es por qué hacer esto:

public int metodo () {}

int Intefaz.metodo () {
    metodo ();
}

Es decir, implementar el método de forma implícita y luego el de forma explícita que dentro llama al mismo método implicito.

0voto

Leonardo-Tadei comentado

No entiendo lo que querés decir con que el método "es accesible desde la interfaz"

Por definición, una interfaz justamente lo que no tiene es implementación, y por tanto la interfaz jamás va a acceder a nada porque no tiene código.

Los que sí tienen código serán las clases que implementen dicha interfaz...

Volviendo a tu pregunta, en los lenguajes con sobrecarga de métodos como C#, tenés que poder explicitar cual método responderá a una llamada. Como en este caso los métodos se llaman igual, la sintaxis esa debería garantizar que si se hace una llamada casteada como IEnumerable el método devuelva lo mismo que si se pide el enumerador al objeto.

a = productos.getEnumerator() vs a = (IEnumerable) productos.getEnumerator()

Podrías probarlo poniendo distintas salidas en ambos métodos y ver en qué situación se llama a cada uno.

Saludos!

0voto

votagus comentado

No me expresé bien, lo que intenté decir es que solo será accesible por medio de un cast:

(Interfaz) clase.metodo ();

Así como supones, si los métodos tienen implementaciones distintas entonces tiene sentido hacerlo de forma explícita, pero dado que con la implementación implícita basta para que el método sea accesible de ambas formas:

clase.metodo ();
(Interfaz) clase.metodo ();

No le veo el sentido a hacer una implementación explícita que llame al método implícito.

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta