sobreescritura sobrecarga polimorfico metodos ejemplos c# java methods overloading

polimorfico - sobrecarga de metodos c# pdf



Método de sobrecarga. ¿Puedes abusar de eso? (16)

¿Cuál es la mejor práctica al definir varios métodos que devuelven la misma forma de datos con diferentes filtros? ¿Nombres de métodos explícitos o métodos sobrecargados?

Por ejemplo. Si tengo algunos Productos y estoy sacando de una base de datos

forma explícita:

public List<Product> GetProduct(int productId) { // return a List } public List<Product> GetProductByCategory(Category category) { // return a List } public List<Product> GetProductByName(string Name ) { // return a List }

modo sobrecargado:

public List<Product> GetProducts() { // return a List of all products } public List<Product> GetProducts(Category category) { // return a List by Category } public List<Product> GetProducts(string searchString ) { // return a List by search string }

Me doy cuenta de que puede entrar en un problema con firmas similares , pero si está pasando objetos en lugar de tipos básicos (cadena, int, char, DateTime, etc.) esto será un problema menor. Entonces ... ¿es una buena idea sobrecargar un método para reducir el número de métodos que tiene y para mayor claridad, o debería cada método que filtra los datos de una manera diferente tener un nombre de método diferente ?


¿Puedes abusar de eso? bueno, sí, eso es verdad

Sin embargo, los ejemplos que ha proporcionado son ejemplos perfectos de cuándo usar la sobrecarga de métodos. Todos realizan la misma función, ¿por qué darles nombres diferentes solo porque les pasas tipos diferentes?

La regla principal es hacer lo más claro y fácil de entender. No use la sobrecarga solo para ser astuto o inteligente, hágalo cuando tenga sentido. Otros desarrolladores también podrían estar trabajando en este código. Desea hacer que sea lo más fácil posible que ellos recojan y comprendan el código y sean capaces de implementar cambios sin implementar errores.


El punto de sobrecarga para facilitar la curva de aprendizaje de alguien que usa su código ... y para permitirle usar esquemas de nomenclatura que informan al usuario sobre lo que hace el método.

Si tiene diez métodos diferentes que devuelven una colección de empleados, generando diez nombres diferentes (¡especialmente si comienzan con letras diferentes!) Hace que aparezcan como entradas múltiples en el menú desplegable intellisense de los usuarios, extendiendo la longitud del desplegable, y ocultando la distinción entre el conjunto de diez métodos que devuelven una colección de empleados, y cualquier otro método que haya en su clase ...

Piensa en lo que ya hace cumplir el .Net framework para, digamos, constructores e indexadores ... Todos están obligados a tener el mismo nombre, y solo puedes crear múltiplos sobrecargándolos ...

Si los sobrecarga, todos aparecerán como uno, con sus firmas y comentarios dispares en el costado.

No debe sobrecargar dos métodos si realizan funciones diferentes o no relacionadas ...

En cuanto a la confusión que puede existir cuando desea sobrecargar dos métodos con la misma firma por tipo que en

public List<Employee> GetEmployees(int supervisorId); public List<Employee> GetEmployees(int departmentId); // Not Allowed !!

Bueno, puedes crear tipos separados como envoltorios para el tipo de núcleo ofensivo para distinguir las firmas.

public struct EmployeeId { private int empId; public int EmployeeId { get { return empId; } set { empId = value; } } public EmployeeId(int employeId) { empId = employeeId; } } public struct DepartmentId { // analogous content } // Now it''s fine, as the parameters are defined as distinct types... public List<Employee> GetEmployees(EmployeeId supervisorId); public List<Employee> GetEmployees(DepartmentId departmentId);


He visto la sobrecarga excesiva cuando solo tienes diferencias sutiles en los argumentos del método. Por ejemplo:

public List<Product> GetProduct(int productId) { // return a List } public List<Product> GetProduct(int productId, int ownerId ) { // return a List } public List<Product> GetProduct(int productId, int vendorId, boolean printInvoice) { // return a List }

En mi pequeño ejemplo, rápidamente no queda claro si el segundo argumento int debería ser el propietario o la identificación del cliente.


La sobrecarga es un comportamiento polimórfico deseable. Ayuda al programador humano a recordar el nombre del método. Si explícito es redundante con el parámetro tipo, entonces es malo. Si el parámetro tipo no implica lo que el método está haciendo, entonces explícito comienza a tener sentido.

En su ejemplo, getProductByName es el único caso en el que lo explícito puede tener sentido, ya que es posible que desee obtener el producto mediante alguna otra cadena. Este problema fue causado por la ambigüedad de los tipos primitivos; getProduct (Name n) podría ser una mejor solución de sobrecarga en algunos casos.


Me gusta sobrecargar mis métodos para que más tarde en el intellisense no tenga un millón del mismo método. Y me parece más lógico tenerlo sobrecargado en vez de llamarlo de manera diferente una docena de veces.


Otra opción es usar un objeto Query para construir la "cláusula WHERE". Entonces solo tendrías un método como este:

public List<Product> GetProducts(Query query)

El objeto Query contiene la condición expresada en una forma orientada a objetos. Los GetProducts obtienen la consulta "analizando" el objeto Query.

http://martinfowler.com/eaaCatalog/queryObject.html


Por lo que puedo decir, no tendrás menos métodos, solo menos nombres. Por lo general, prefiero el método de nombres sobrecargado de nombres, pero no creo que realmente haga mucha diferencia, siempre y cuando comentes y documentes bien tu código (lo cual debes hacer en ambos casos).


Probablemente necesites algunos estándares para todo el proyecto. Personalmente, encuentro que los métodos sobrecargados son mucho más fáciles de leer. Si tienes el soporte IDE, ve por ello.


Puedes usar Overloading todo lo que quieras. También desde el punto de vista de las mejores prácticas, se recomienda que use Sobrecarga si está tratando de realizar la misma "operación" (holísticamente) en los datos. Por ejemplo, getProduct ()

Además, si ve la API de Java, la sobrecarga está en todas partes. No encontrarías un respaldo mayor que eso.


Qué tal si

public IList<Product> GetProducts() { /* Return all. */} public IList<Product> GetProductBy(int productId) {...} public IList<Product> GetProductBy(Category category) {...} public IList<Product> GetProductBy(string Name ) {...}

¿Y así?


Sí, la sobrecarga puede ser usada en exceso.

Descubrí que la clave para determinar si una sobrecarga está justificada o no es considerar al público, no al compilador, sino al programador de mantenimiento que vendrá en semanas / meses / años y tiene que entender qué es el código. tratando de lograr

Un nombre de método simple como GetProducts () es claro y comprensible, pero no deja mucho que decir.

En muchos casos, si el parámetro pasado a GetProducts () tiene un buen nombre, el técnico de mantenimiento podrá determinar qué hace la sobrecarga, pero eso depende de una buena disciplina de nomenclatura en el punto de uso, que no se puede aplicar. Lo que puede hacer cumplir es el nombre del método que están llamando.

La pauta que sigo es solo sobrecargar los métodos si son intercambiables, si hacen lo mismo. De esta forma, no me importa qué versión invoca el consumidor de mi clase, ya que son equivalentes.

Para ilustrar, felizmente usaría sobrecargas para un método DeleteFile ():

void DeleteFile(string filePath); void DeleteFile(FileInfo file); void DeleteFile(DirectoryInfo directory, string fileName);

Sin embargo, para sus ejemplos, usaría nombres separados:

public IList<Product> GetProductById(int productId) {...} public IList<Product> GetProductByCategory(Category category) {...} public IList<Product> GetProductByName(string Name ) {...}

Tener los nombres completos hace que el código sea más explícito para el tipo de mantenimiento (que bien podría ser yo). Evita problemas con colisiones de firmas:

// No collisions, even though both methods take int parameters public IList<Employee> GetEmployeesBySupervisor(int supervisorId); public IList<Employee> GetEmployeesByDepartment(int departmentId);

También existe la oportunidad de introducir sobrecarga para cada propósito:

// Examples for GetEmployees public IList<Employee> GetEmployeesBySupervisor(int supervisorId); public IList<Employee> GetEmployeesBySupervisor(Supervisor supervisor); public IList<Employee> GetEmployeesBySupervisor(Person supervisor); public IList<Employee> GetEmployeesByDepartment(int departmentId); public IList<Employee> GetEmployeesByDepartment(Department department); // Examples for GetProduct public IList<Product> GetProductById(int productId) {...} public IList<Product> GetProductById(params int[] productId) {...} public IList<Product> GetProductByCategory(Category category) {...} public IList<Product> GetProductByCategory(IEnumerable<Category> category) {...} public IList<Product> GetProductByCategory(params Category[] category) {...}

El código se lee mucho más de lo que está escrito, incluso si nunca vuelve al código después del control inicial en el control de la fuente, todavía leerá esa línea de código un par de docenas de veces mientras escribe el código. código que sigue.

Por último, a menos que esté escribiendo código descartable, debe permitir que otras personas llamen a su código desde otros idiomas. Parece que la mayoría de los sistemas empresariales terminan estando en producción mucho más allá de su uso por fecha. Puede ser que el código que consume tu clase en 2016 termine escrito en VB.NET, C # 6.0, F # o algo completamente nuevo que aún no se haya inventado. Es posible que el idioma no admita sobrecargas.


Sí, puede abusar de él, sin embargo, aquí hay otro concepto que podría ayudar a mantener el uso de él bajo control ...

Si está utilizando .Net 3.5+ y necesita aplicar varios filtros, probablemente sea mejor usar IQueryable y encadenamiento, es decir,

GetQuery<Type>().ApplyCategoryFilter(category).ApplyProductNameFilter(productName);

De esta forma, puede reutilizar la lógica de filtrado una y otra vez donde sea que la necesite.

public static IQueryable<T> ApplyXYZFilter(this IQueryable<T> query, string filter) { return query.Where(XYZ => XYZ == filter); }


Soy un fanático total de la forma "explícita": darle a cada función un nombre diferente. Incluso refactoreé un código que tenía muchas funciones Add(...) en el pasado, AddRecord(const Record&) , AddCell(const Cell&) , etc.

Creo que esto ayuda a evitar algunas confusiones, conversiones inadvertidas (en C ++, al menos) y advertencias del compilador, y mejora la claridad.

Quizás en algunos casos necesites la otra estrategia. No he encontrado uno todavía.


Una breve mirada al marco debería convencerlo de que numerosas sobrecargas son una situación aceptada. En vista de la gran cantidad de sobrecargas, el diseño de sobrecargas para la usabilidad se aborda directamente en la sección 5.1.1 de las Pautas de diseño de Microsoft Framework (Kwalina y Abrams, 2006). Aquí hay un breve prècis de esa sección:

  • SI intenta usar nombres de parámetros descriptivos para indicar el valor predeterminado utilizado por sobrecargas más cortas.

  • EVITE la variación arbitraria de nombres de parámetros en sobrecargas.

  • EVITE ser inconsistente en el orden de los parámetros en los miembros sobrecargados.

  • HAGA que solo la sobrecarga más larga sea virtual (si se requiere extensibilidad). Las sobrecargas más cortas deberían simplemente solicitar una sobrecarga más larga.

  • NO use out parámetros ref o out para sobrecargar los miembros.

  • HAGA que se pase null por argumentos opcionales.

  • use la sobrecarga de miembros en lugar de definir miembros con argumentos predeterminados.


Una cosa que puede considerar es que no puede exponer métodos sobrecargados como contratos de operación en un servicio web de WCF. Entonces, si crees que alguna vez necesitarás hacer esto, sería un argumento para usar diferentes nombres de métodos.

Otro argumento para diferentes nombres de métodos es que pueden ser más fácilmente detectables usando intellisense.

Pero existen ventajas y desventajas para cualquiera de las dos opciones: todo diseño es una solución de compromiso.


sí, puedes abusar de él. En su ejemplo, parecería que el primero y el tercero probablemente devolverían un solo artículo, mientras que el segundo devolvería varios. Si eso es correcto, entonces llamaría al primer y tercer GetProduct y al segundo GetProducts o GetProductList

si este no es el caso y los tres devuelven varios (como si lo pasara productID 5, devuelve cualquier elemento con 5 en el productid, o devuelve cualquier elemento con el parámetro de cadena en su nombre) entonces llamaría a los tres GetProducts o GetProductList y los reemplaza a todos.

En cualquier caso, el nombre debe reflejar lo que hace la función, por lo que llamarlo GetProduct (singular) cuando devuelve una lista de Productos no tiene un buen nombre de función. IMNSHO