tutorial oriented language help documentacion development concepts c# oop

language - object oriented concepts c#



¿Qué es Interface Duck Typing? (4)

Escuché la palabra Interface Duck Typing, pero no entiendo para nada ¿qué es? Así que leí un wiki sobre esto y me dijeron:

En la programación de computadoras con lenguajes de programación orientados a objetos, la tipificación de pato es un estilo de tipeo en el cual los métodos y propiedades de un objeto determinan la semántica válida, en lugar de su herencia de una clase particular o implementación de una interfaz explícita. El nombre del concepto se refiere a la prueba de pato.

Pero aún no podía entender de qué se trataba. Así que vi su programa pero usan dynamic palabra clave dynamic para llamar a la función quack() y feather() de todas las clases.

Me gustaría pedirles a todos que expliquen de manera sencilla qué es Interface Duck Typing y cómo implementarlo en C # v2.0 porque no existe dynamic palabra clave dynamic .

using System; namespace DuckTyping { public class Duck { public void Quack() { Console.WriteLine("Quaaaaaack!"); } public void Feathers() { Console.WriteLine("The duck has white and gray feathers."); } } public class Person { public void Quack() { Console.WriteLine("The person imitates a duck."); } public void Feathers() { Console.WriteLine("The person takes a feather from the ground and shows it."); } } internal class Program { private static void InTheForest(dynamic duck) { duck.Quack(); duck.Feathers(); } private static void Game() { Duck donald = new Duck(); Person john = new Person(); InTheForest(donald); InTheForest(john); } private static void Main() { Game(); } } }


La tipificación de pato permite pasar un objeto a un método que espera un cierto tipo incluso si no hereda de ese tipo. Todo lo que tiene que hacer es apoyar los métodos y las propiedades del tipo esperado en uso por el método. Destaco esa última frase por una razón. Supongamos que tenemos un método que toma en una instancia de pato, y otro método que toma en una instancia de conejo. En un lenguaje de tipado dinámico que admite el tipado de pato, puedo pasar mi objeto al primer método siempre que mi objeto admita los métodos y propiedades de pato en uso por ese método. Del mismo modo, puedo pasar mi objeto al segundo método, siempre que admita los métodos y propiedades de rabbit invocados por el segundo método. ¿Es mi objeto un pato o es un conejo? Al igual que la imagen de arriba, no es ninguna de las dos cosas. En muchos (si no en la mayoría) de los lenguajes dinámicos, mi objeto no tiene que admitir todos los métodos y propiedades de pato para pasar a un método que espera un pato. Lo mismo ocurre con un método que espera un conejo. Solo necesita admitir los métodos y las propiedades del tipo esperado que el método llama en realidad.

Por favor refiérase a esto para tener una idea acerca de Duck Typing

http://haacked.com/archive/2007/08/19/why-duck-typing-matters-to-c-developers.aspx/


C # tiene un sistema de tipo nominal, por lo que la compatibilidad de los tipos se basa en sus nombres. En su ejemplo, tiene dos clases con un método Quack , sin embargo, no hay forma de escribir un método que pueda tomar instancias de estas dos clases e invocar su método Quack .

En C # 2, la solución sería introducir una interfaz y hacer que ambas clases la implementen:

public interface IQuack { void Quack(); } public class Duck : IQuack { } public class Human : IQuack { }

ahora puedes crear un método que tome una instancia de IQuack y pueda invocar Human.Quack y Duck.Quack través de ella. En C #, los métodos se resuelven "temprano" en tiempo de compilación, por lo que debe crear un tipo con nombre que admita las operaciones que el método necesita para que la compilación tenga éxito. Tenga en cuenta que todavía hay un elemento de tiempo de ejecución para llamar a estos métodos, ya que la implementación real de IQuack.Quack necesita resolverse en tiempo de ejecución dependiendo del tipo real del argumento.

En un sistema de tipado de patos, no se intenta validar que exista un método antes del tiempo de ejecución. Todo lo que se requiere es que un objeto dado admita la operación en el sentido de que tiene el nombre correcto y toma el número requerido de parámetros (ninguno en este caso), de ahí la expresión ''si grazna como un pato''.

Duck typing en C # 2 solo se puede hacer usando la reflexión, en este caso, aceptaría un argumento de object y buscaría los métodos necesarios usted mismo:

public static void MakeQuack(object duck) { MethodInfo quackMethod = duck.GetType().GetMethod("Quack", Type.EmptyTypes, null); if (quackMethod!=null) { quackMethod.Invoke(duck, new object[] { }); } else { throw new ArgumentException("No Quack() method found on target"); } }

C # 4 hace esto mucho más simple con dynamic :

public static void MakeQuack(dynamic duck) { duck.Quack(); }


Diría que es una forma de codificación en la que le dices al compilador:

"Oye, créeme, sé qué métodos y propiedades admite este objeto. No es necesario que los verifiques mientras codigo".

Una vez que ejecute su aplicación, el compilador mostrará: "Ok, veamos si puedo confiar en usted. Déjeme hacer un enlace en tiempo de ejecución".

Si luego cometió un error, como usar un método no compatible, el compilador gritará: "¡Oye, esto no es compatible! ¡Comprueba mi RuntimeBinderException!"


Acerca de Duck Typing:

No necesitamos saber cuál es el objeto, pero solo queremos que el objeto haga algo si puede hacerlo.

Ejemplo:

Ejemplo, si aquí están las cosas que queremos que hagan los siguientes objetos.

PleaseWalk(new Dog()); PleaseRun(new Duck()); PleaseWalk(new Cup()); PleaseFly(new Man()); PleaseFly(new Bird());

Y, aquí está el resultado después de que solicitemos que los objetos anteriores hagan las cosas.

Entonces, no necesitamos verificar cuál es el objeto, pero podemos dejar que haga algo suficiente. Aquí está el código que he escrito en C #.

private void PleaseWalk(object obj) { string Method = "Walk"; MethodInfo walkMethod = obj.GetType().GetMethod(Method, Type.EmptyTypes, null); if (walkMethod != null) { walkMethod.Invoke(obj, new object[] { }); } else { Console.WriteLine(string.Format("I can not {0} because {1}", Method, WhoAreYou(obj))); } } private string WhoAreYou(object unknown) { MethodInfo whoAreYou = unknown.GetType().GetMethod("WhoAreYou", Type.EmptyTypes, null); return whoAreYou.Invoke(unknown, new object[] { }).ToString(); }