from convertir codigo c# java .net interface

c# - from - convertir codigo java ac



Una diferencia de estilo: IDictionary vs Dictionary (13)

El uso de interfaces significa que "diccionario" en el siguiente código podría ser cualquier implementación de IDictionary.

Dictionary1 dictionary = new Dictionary1(); dictionary.operation1(); // if operation1 is implemented only in Dictionary1() this will fail for every other implementation

Se ve mejor cuando oculta la construcción del objeto:

IDictionary dictionary = DictionaryFactory.getDictionary(...);

Tengo un amigo que acaba de entrar en el desarrollo de .NET después de desarrollar en Java durante años y, después de ver algunos de sus códigos, noto que hace lo siguiente con bastante frecuencia:

IDictionary<string, MyClass> dictionary = new Dictionary<string, MyClass>();

Está declarando el diccionario como la Interfaz en lugar de la Clase. Normalmente haré lo siguiente:

Dictionary<string, MyClass> dictionary = new Dictionary<string, MyClass>();

Solo usaría la interfaz IDictionary cuando sea necesario (digamos, por ejemplo, pasar el diccionario a un método que acepte una interfaz IDictionary).

Mi pregunta es: ¿hay algún mérito en su forma de hacer las cosas? ¿Es esta una práctica común en Java?


En la situación descrita, casi todos los desarrolladores de Java usarían la interfaz para declarar la variable. La forma en que se utilizan las colecciones de Java es probablemente uno de los mejores ejemplos:

Map map = new HashMap(); List list = new ArrayList();

Supongo que solo logra un acoplamiento flexible en muchas situaciones.


Esta práctica no se limita a Java.

También se usa a menudo en .NET cuando desea desvincular la instancia del objeto de la clase que está utilizando. Si usa la interfaz en lugar de la clase, puede cambiar el tipo de respaldo siempre que sea necesario sin romper el resto del código.

También verá que esta práctica se usa mucho para tratar con contenedores de IoC y la instanciación usando el patrón de Fábrica.


He descubierto que para las variables locales generalmente no importa si usas la interfaz o la clase concreta.

A diferencia de los miembros de la clase o las firmas de métodos, hay muy poco esfuerzo de refactorización si decide cambiar los tipos, y la variable tampoco está visible fuera de su sitio de uso. De hecho, cuando se usa var para declarar locales, no se obtiene el tipo de interfaz, sino el tipo de clase (a menos que se transfiera explícitamente a la interfaz).

Sin embargo, al declarar métodos, miembros de clase o interfaces, creo que le ahorrará un poco de dolor de cabeza utilizar el tipo de interfaz por adelantado, en lugar de acoplar la API pública a un tipo de clase específico.


He encontrado la misma situación con un desarrollador de Java. Él ejemplifica colecciones Y objetos a su interfaz de la misma manera. Por ejemplo,

IAccount account = new Account();

Las propiedades siempre se obtienen / configuran como interfaces. Esto causa problemas con la serialización, que se explica muy bien here


Las colecciones de Java incluyen una multitud de implementaciones. Por lo tanto, es mucho más fácil para mí hacer uso de

List<String> myList = new ArrayList<String>();

Luego, en el futuro, cuando me doy cuenta de que necesito que "myList" esté seguro de subprocesos para simplemente cambiar esta única línea a

List<String> myList = new Vector<String>();

Y no cambie ninguna otra línea de código. Esto incluye getters / setters también. Si observa el número de implementaciones de Map, por ejemplo, puede imaginar por qué esta podría ser una buena práctica. En otros idiomas, donde solo hay un par de implementaciones para algo (lo siento, no es un chico grande de .NET) pero en Objective-C realmente solo hay NSDictionary y NSMutableDictionary. Entonces, no tiene tanto sentido.

Editar:

Fallo al golpear en uno de mis puntos clave (aludido a él con el getter / setters).

Lo anterior le permite tener:

public void setMyList(List<String> myList) { this.myList = myList; }

Y el cliente que usa esta llamada no necesita preocuparse por la implementación subyacente. Usar cualquier objeto que se ajuste a la interfaz de la Lista que puedan tener.


Muy a menudo, verá el tipo de interfaz (IDictionary) que se usa cuando el miembro está expuesto a un código externo, ya sea que esté fuera del ensamblaje o justo fuera de la clase. Normalmente, la mayoría de los desarrolladores usan el tipo concreto internamente para una definición de clase mientras exponen una propiedad encapsulada utilizando el tipo de interfaz. De esta forma, pueden aprovechar las capacidades del tipo concreto, pero si cambian el tipo concreto, la interfaz de la clase declarante no necesita cambiar.

public class Widget { private Dictionary<string, string> map = new Dictionary<string, string>(); public IDictionary<string, string> Map { get { return map; } } }

más tarde puede convertirse en:

class SpecialMap<TKey, TValue> : IDictionary<TKey, TValue> { ... } public class Widget { private SpecialMap<string, string> map = new SpecialMap<string, string>(); public IDictionary<string, string> Map { get { return map; } } }

sin cambiar la interfaz de Widget y tener que cambiar otro código que ya lo esté usando.


Para variables locales y campos privados, que ya son detalles de implementación, es mejor usar tipos concretos que interfaces para las declaraciones porque las clases concretas ofrecen un aumento de rendimiento (el despacho directo es más rápido que el despacho virtual / de interfaz). El JIT también podrá aplicar métodos en línea más fácilmente si no se transfiere innecesariamente a los tipos de interfaz en los detalles de implementación local. Si se devuelve una instancia de un tipo concreto de un método que devuelve una interfaz, el lanzamiento es automático.


Por lo que he visto, los desarrolladores de Java tienden a usar la abstracción (y los patrones de diseño) con más frecuencia que los desarrolladores de .NET. Esto parece ser otro ejemplo: ¿por qué declarar la clase concreta cuando esencialmente solo estará trabajando con los miembros de la interfaz?


Si IDictionary es un tipo "más genérico" que el diccionario, tiene sentido utilizar el tipo más genérico para declarar variables. De esta forma, no tiene que preocuparse demasiado por la clase de implementación asignada a la variable y puede cambiar el tipo fácilmente en el futuro sin tener que cambiar una gran cantidad de código siguiente. Por ejemplo, en Java a menudo se considera mejor hacerlo

List<Integer> intList=new LinkedList<Integer>();

de lo que es hacer

LinkedList<Integer> intList=new LinkedList<Integer>();

De esa forma, estoy seguro de que todos los códigos siguientes tratan la lista como Lista y no como Lista Vinculada, lo que hace que en el futuro sea fácil cambiar LinkedList por Vector o cualquier otra clase que implemente List. Yo diría que esto es común a Java y una buena programación en general.


Siempre debe intentar programar en la interfaz en lugar de la clase concreta.

En Java o cualquier otro lenguaje de programación orientado a objetos.

En .NET world es común usar una I para indicar que es una interfaz lo que estás usando. Creo que esto es más común porque en C # no tienen implements y se extends para referirse a herencia de clase vs interfaz.

Creo que el suero escribiría

class MyClass:ISome,Other,IMore { }

Y puedes decir que ISome IMore son interfaces mientras que Other es una clase

En Java no hay necesidad de tal cosa

class MyClass extends Other implements Some, More { }

El concepto aún se aplica, debe intentar codificar a la interfaz.


Tu amigo está siguiendo el muy útil principio:

"Resúmate a ti mismo de los detalles de implementación"


Viniendo de un mundo de Java, estoy de acuerdo en que el mantra "programa a una interfaz" se encuentra dentro de ti. Al programar en una interfaz, no en una implementación, usted hace que sus métodos sean más extensibles a las necesidades futuras.