¿La sobrecarga de métodos es un tipo de polimorfismo? A mí me parece simplemente la diferenciación de métodos con el mismo nombre y diferentes parámetros. Entonces, stuff(Thing t)
y stuff(Thing t, int n)
son métodos completamente diferentes en lo que respecta al compilador y el tiempo de ejecución.
Crea la ilusión, por parte de la persona que llama, de que es el mismo método que actúa de manera diferente en diferentes tipos de objetos: el polimorfismo. Pero eso es solo una ilusión, porque en realidad stuff(Thing t)
y stuff(Thing t, int n)
son métodos completamente diferentes.
¿El método está sobrecargando algo más que el azúcar sintáctico? ¿Me estoy perdiendo de algo?
Una definición común para el azúcar sintáctico es que es puramente local . Lo que significa que cambiar un fragmento de código a su equivalente 'endulzado', o viceversa, implica cambios locales que no afectan la estructura general del programa. Y creo que la sobrecarga de métodos se ajusta precisamente a este criterio. Veamos un ejemplo para demostrar:
Considera una clase:
class Reader {
public String read(Book b){
// .. translate the book to text
}
public String read(File b){
// .. translate the file to text
}
}
Ahora considere otra clase que usa esta clase:
/* might not be the best example */
class FileProcessor {
Reader reader = new Reader();
public void process(File file){
String text = reader.read(file);
// .. do stuff with the text
}
}
Bueno. Ahora veamos qué necesita cambiar si reemplazamos la sobrecarga de métodos con métodos regulares:
Los read
métodos en Reader
cambio a readBook(Book)
y readFile(file)
. Solo es cuestión de cambiar sus nombres.
El código de llamada FileProcessor
cambia ligeramente: reader.read(file)
cambia a reader.readFile(file)
.
Y eso es.
Como puede ver, la diferencia entre usar la sobrecarga de métodos y no usarla es puramente local . Y es por eso que creo que califica como azúcar sintáctico puro.
Me gustaría escuchar sus objeciones si tiene alguna, tal vez me estoy perdiendo algo.
fuente
Respuestas:
Para responder a esto, primero necesita una definición de "azúcar sintáctico". Iré con Wikipedia :
Entonces, bajo esta definición, características como los varargs de Java o la comprensión de Scala son azúcar sintáctica: se traducen en características subyacentes del lenguaje (una matriz en el primer caso, llamadas a map / flatmap / filter en el segundo), y eliminarlas sería No cambie las cosas que puede hacer con el idioma.
La sobrecarga de métodos, sin embargo, no es azúcar sintáctica bajo esta definición, porque eliminarla cambiaría fundamentalmente el idioma (ya no sería capaz de enviar un comportamiento distinto basado en argumentos).
Es cierto que puede simular la sobrecarga de métodos siempre que tenga alguna forma de acceder a los argumentos de un método, y puede usar una construcción "if" basada en los argumentos que se le dan. Pero si considera ese azúcar sintáctico, debería considerar cualquier cosa por encima de una máquina de Turing para que también sea azúcar sintáctico.
fuente
sum(numbersArray)
y ensum(numbersList)
lugar desumArray(numbersArray)
ysumList(numbersList)
. Estoy de acuerdo con Doval, parece un mero azúcar sintético.instanceof
, clases, herencia, las interfaces, los genéricos, reflexión o especificadores de acceso que utilicenif
,while
y los operadores booleanos, con exactamente la misma semántica . No hay casos de esquina. Tenga en cuenta que no le estoy desafiando a que calcule las mismas cosas que los usos específicos de esas construcciones. Ya sé que puedes calcular cualquier cosa usando lógica booleana y ramificación / bucle. Te estoy pidiendo para implementar copias perfectas de la semántica de las características del lenguaje, incluidas las garantías estáticos que proporcionan (comprobaciones en tiempo de compilación todavía deben hacerse en tiempo de compilación.)El término azúcar sintáctico generalmente se refiere a casos en los que la característica se define mediante una sustitución. El lenguaje no define lo que hace una característica, sino que define que es exactamente equivalente a otra cosa. Entonces, por ejemplo, bucles for-each
Se convierte en:
O tome una función con argumentos variables:
Que se convierte en:
Por lo tanto, hay una sustitución trivial de la sintaxis para implementar la característica en términos de otras características.
Veamos la sobrecarga de métodos.
Esto puede reescribirse como:
Pero no es equivalente a eso. Dentro del modelo de Java, esto es algo diferente.
foo(int a)
no implementa unafoo_int
función para ser creada. Java no implementa la sobrecarga de métodos al dar nombres divertidos a funciones ambiguas. Para contar como azúcar sintáctico, Java tendría que fingir que realmente escribiófoo_int
yfoo_double
funciona, pero no es así.fuente
But, the transformation isn't trivial. At the least, you have to determine the types of the parameters.
muy incompleta porque no es necesario determinar los tipos ; son conocidos en tiempo de compilación.foo(int)
/foo(double)
yfoo_int
/foo_double
? Realmente no conozco muy bien Java, pero me imagino que tal cambio de nombre realmente ocurre en JVM (bueno, probablemente usando enfoo(args)
lugar defoo_args
) al menos en C ++ con símbolo de manipulación (ok, el símbolo de manipulación es técnicamente un detalle de implementación y no parte del lenguaje)for
bucle mejorado no es más expresivo que Java sin él. (Es más agradable, más conciso, más legible y, en general, mejor, diría, pero no más expresivo). Sin embargo, no estoy seguro sobre el caso de sobrecarga. Probablemente tendré que volver a leer el periódico para estar seguro. Mi instinto dice que es azúcar sintáctico, pero no estoy seguro.Dado que el cambio de nombre funciona, ¿no tiene que ser nada más que azúcar sintáctica?
Le permite a la persona que llama imaginar que está llamando a la misma función, cuando no lo está. Pero podía saber los nombres reales de todas sus funciones. Solo si fuera posible lograr un polimorfismo retrasado al pasar una variable sin tipo a una función con tipo y establecer su tipo para que la llamada pueda ir a la versión correcta de acuerdo con el nombre, esta sería una característica verdadera del lenguaje.
Desafortunadamente, nunca he visto un idioma hacer esto. Cuando hay ambigüedad, estos compiladores no lo resuelven, insisten en que el escritor lo resuelva por ellos.
fuente
dynamic
entonces resolución de sobrecarga se produce en tiempo de ejecución, no en tiempo de compilación . Eso es el despacho múltiple, y no se puede replicar cambiando el nombre de las funciones.Dependiendo del idioma, es azúcar sintáctico o no.
En C ++, por ejemplo, puede hacer cosas usando sobrecarga y plantillas que no serían posibles sin complicaciones (escriba manualmente todas las instancias de la plantilla o agregue muchos parámetros de plantilla).
Tenga en cuenta que el despacho dinámico es una forma de sobrecarga, resuelta dinámicamente en algunos parámetros (para algunos idiomas solo uno especial, esto , pero no todos los idiomas son tan limitados), y no llamaría a esa forma de sobrecarga de azúcar sintáctico.
fuente
Para los idiomas contemporáneos, es solo azúcar sintáctico; de una manera completamente independiente del lenguaje, es más que eso.
Anteriormente, esta respuesta decía simplemente que es más que azúcar sintáctica, pero si lo verá en los comentarios, Falco planteó el punto de que había una pieza del rompecabezas que los lenguajes contemporáneos parecen faltar; no mezclan la sobrecarga de métodos con la determinación dinámica de qué función llamar en el mismo paso. Esto se aclarará más adelante.
He aquí por qué debería ser más.
Considere un lenguaje que admita sobrecarga de métodos y variables sin tipo. Podría tener los siguientes prototipos de métodos:
En algunos idiomas, es probable que se resigne a saber en tiempo de compilación a cuál de estos se llamaría mediante una línea de código determinada. Pero en algunos idiomas, no todas las variables se escriben (o todas se escriben implícitamente como
Object
o lo que sea), así que imagine construir un diccionario cuyas claves correspondan con valores de diferentes tipos:Ahora bien, ¿qué pasaría si quisieras postular
someFunction
a uno de esos números de habitación? A esto le llamas:¿Se
someFunction(int)
llama o sesomeFunction(string)
llama? Aquí puede ver un ejemplo en el que estos no son métodos totalmente ortogonales, especialmente en lenguajes de nivel superior. El lenguaje tiene que descubrir, durante el tiempo de ejecución, a cuál de estos llamar, por lo que aún debe considerar que estos son al menos el mismo método.¿Por qué no simplemente usar plantillas? ¿Por qué no simplemente usar un argumento sin tipo?
Flexibilidad y control de grano más fino. A veces, usar plantillas / argumentos sin tipo es un mejor enfoque, pero a veces no lo son.
Debe pensar en casos en los que, por ejemplo, podría tener dos firmas de métodos que toman un
int
y unstring
como argumentos, pero donde el orden es diferente en cada firma. Es muy posible que tenga una buena razón para hacerlo, ya que la implementación de cada firma puede hacer en gran medida lo mismo, pero con un giro ligeramente diferente; el registro podría ser diferente, por ejemplo. O incluso si hacen exactamente lo mismo, es posible que pueda recopilar automáticamente cierta información solo en el orden en que se especificaron los argumentos. Técnicamente, podría usar declaraciones de seudoconmutador para determinar el tipo de cada uno de los argumentos pasados, pero eso se vuelve desordenado.Entonces, ¿este siguiente ejemplo es una mala práctica de programación?
Sí, en general. En este ejemplo particular, podría evitar que alguien intente aplicar esto a ciertos tipos primitivos y recupere comportamientos inesperados (lo que podría ser algo bueno); pero supongamos que abrevié el código anterior y que, de hecho, usted tiene sobrecargas para todos los tipos primitivos, así como para
Object
s. Entonces este siguiente fragmento de código es realmente más apropiado:Pero, ¿qué sucede si solo necesita usar esto para
int
systring
s, y qué pasa si desea que se vuelva verdadero en función de condiciones más simples o más complicadas en consecuencia? Entonces tiene una buena razón para usar la sobrecarga:Pero oye, ¿por qué no solo dar a esas funciones dos nombres diferentes? Todavía tienes la misma cantidad de control de grano fino, ¿no?
Porque, como se indicó anteriormente, algunos hoteles usan números, algunos usan letras y otros usan una combinación de números y letras:
Este todavía no es exactamente el mismo código exacto que usaría en la vida real, pero debería ilustrar el punto que estoy haciendo bien.
Pero ... He aquí por qué no es más que azúcar sintáctica en los idiomas contemporáneos.
Falco planteó el punto en los comentarios de que los lenguajes actuales básicamente no mezclan la sobrecarga de métodos y la selección dinámica de funciones dentro del mismo paso. La forma en que anteriormente entendía que ciertos idiomas funcionaban era que se podía sobrecargar
appearsToBeFirstFloor
en el ejemplo anterior, y luego el idioma determinaría en tiempo de ejecución qué versión de la función se llamará, dependiendo del valor de tiempo de ejecución de la variable sin tipo. Esta confusión se debió en parte al trabajar con lenguajes de tipo ECMA, como ActionScript 3.0, en el que puede aleatorizar fácilmente qué función se llama en una determinada línea de código en tiempo de ejecución.Como ya sabrás, ActionScript 3 no admite la sobrecarga de métodos. En cuanto a VB.NET, puede declarar y establecer variables sin asignar un tipo explícitamente, pero cuando intenta pasar estas variables como argumentos a métodos sobrecargados, aún no desea leer el valor de tiempo de ejecución para determinar qué método llamar; en su lugar, quiere encontrar un método con argumentos de tipo
Object
o sin tipo o algo por el estilo. Por lo que elint
vs.string
ejemplo anterior no funcionaría en ese idioma tampoco. C ++ tiene problemas similares, ya que cuando usa algo como un puntero nulo o algún otro mecanismo como ese, aún requiere que desambigue manualmente el tipo en tiempo de compilación.Entonces, como dice el primer encabezado ...
Para los idiomas contemporáneos, es solo azúcar sintáctico; de una manera completamente independiente del lenguaje, es más que eso. Hacer que la sobrecarga de métodos sea más útil y relevante, como en el ejemplo anterior, en realidad puede ser una buena característica para agregar a un lenguaje existente (como se ha solicitado ampliamente implícitamente para AS3), o también podría servir como uno entre muchos pilares fundamentales diferentes para la creación de un nuevo lenguaje procesal / orientado a objetos.
fuente
this[chooseFunctionNameAtRandom]();
SichooseFunctionNameAtRandom()
devuelve o"punch"
,"kick"
o"dodge"
, a continuación, puede aplicar thusly una manera muy simple al azar elemento en, por ejemplo, la IA de un enemigo en un juego Flash.Realmente depende de su definición de "azúcar sintáctico". Trataré de abordar algunas de las definiciones que se me ocurren:
Una característica es el azúcar sintáctico cuando un programa que lo utiliza siempre se puede traducir en otro que no la utiliza.
Aquí suponemos que existe un conjunto primitivo de características que no se pueden traducir: en otras palabras, no hay bucles del tipo "puede reemplazar la característica X usando la característica Y" y "puede reemplazar la característica Y con la característica X". Si uno de los dos es verdadero, la otra característica se puede expresar en términos de características que no son la primera o es una característica primitiva.
Igual que la definición 1, pero con el requisito adicional de que el programa traducido sea tan seguro para los tipos como el primero, es decir, al desaguar no pierde ningún tipo de información.
La definición del OP: una característica es el azúcar sintáctico si su traducción no cambia la estructura del programa, sino que solo requiere "cambios locales".
Tomemos a Haskell como ejemplo de sobrecarga. Haskell proporciona sobrecarga definida por el usuario a través de clases de tipo. Por ejemplo, las operaciones
+
y*
se definen en laNum
clase de tipo y se puede usar cualquier tipo que tenga una instancia (completa) de dicha clase+
. Por ejemplo:Una cosa bien conocida sobre las clases de tipos de Haskell es que puedes deshacerte de ellas . Es decir, puede traducir cualquier programa que use clases de tipos en un programa equivalente que no las use.
La traducción es bastante simple:
Dada una definición de clase:
Puede traducirlo a un tipo de datos algebraicos:
Aquí
X_P_i
yX_op_i
son selectores . Es decir, un valor de tipo que seX a
aplicaX_P_1
al valor devolverá el valor almacenado en ese campo, por lo que son funciones con tipoX a -> P_i a
(oX a -> t_i
).Para una anología muy aproximada , podría pensar en los valores para type
X a
comostruct
sy luego, six
es de type,X a
las expresiones:podría verse como:
(Es fácil usar solo campos posicionales en lugar de campos con nombre, pero los campos con nombre son más fáciles de manejar en los ejemplos y evitan algún código de placa de caldera).
Dada una declaración de instancia:
Puede traducirlo a una función que, dado los diccionarios para las
C_1 a_1, ..., C_n a_n
clases, devuelve un valor de diccionario (es decir, un valor de tipoX a
) para el tipoT a_1 ... a_n
.En otras palabras, la instancia anterior se puede traducir a una función como:
(Tenga en cuenta que
n
puede ser0
).Y de hecho podemos definirlo como:
donde
op_1 = ...
aop_m = ...
son las definiciones que se encuentran en lainstance
declaración y elget_P_i_T
son las funciones definidas por laP_i
instancia delT
tipo (deben existen porqueP_i
s son superclases deX
).Dada una llamada a una función sobrecargada:
Podemos pasar explícitamente los diccionarios relativos a las restricciones de clase y obtener una llamada equivalente:
Observe cómo las restricciones de clase simplemente se convirtieron en un nuevo argumento. El
+
en el programa traducido es el selector como se explicó anteriormente. En otras palabras, laadd
función traducida , dado el diccionario para el tipo de argumento, primero "desempaquetará" la función real para calcular el resultado usando(+) dictNum
y luego aplicará esta función a los argumentos.Este es solo un esbozo muy rápido sobre todo el asunto. Si está interesado, debe leer los artículos de Simon Peyton Jones et al.
Creo que un enfoque similar podría usarse para sobrecargar en otros idiomas también.
Sin embargo, esto muestra que, si su definición de azúcar sintáctico es (1), la sobrecarga es azúcar sintáctico . Porque puedes deshacerte de él.
Sin embargo, el programa traducido pierde información sobre el programa original. Por ejemplo, no exige que existan instancias para las clases principales. (Aunque las operaciones para extraer los diccionarios de los padres todavía deben ser de ese tipo, puede pasar
undefined
u otros valores polimórficos para que pueda generar un valorX y
sin generar los valores paraP_i y
, por lo que la traducción no pierde todo El tipo de seguridad). Por lo tanto, no es azúcar sintáctico de acuerdo con (2)En cuanto a (3). No sé si la respuesta debería ser un sí o un no.
Yo diría que no porque, por ejemplo, una declaración de instancia se convierte en una definición de función. Las funciones que están sobrecargadas obtienen un nuevo parámetro (lo que significa que cambia tanto la definición como todas las llamadas).
Yo diría que sí porque los dos programas todavía se asignan uno a uno, por lo que la "estructura" en realidad no cambia tanto.
Dicho esto, diría que las ventajas pragmáticas introducidas por la sobrecarga son tan grandes que usar un término "despectivo" como "azúcar sintáctico" no parece correcto.
Puede traducir toda la sintaxis de Haskell a un lenguaje Core muy simple (que en realidad se hace al compilar), por lo que la mayoría de la sintaxis de Haskell podría verse como "azúcar sintáctico" para algo que es solo cálculo lambda más un poco de nuevas construcciones. Sin embargo, podemos estar de acuerdo en que los programas de Haskell son mucho más fáciles de manejar y muy concisos, mientras que los programas traducidos son bastante más difíciles de leer o pensar.
fuente
Si el despacho se resuelve en tiempo de compilación, dependiendo solo del tipo estático de la expresión del argumento, entonces ciertamente puede argumentar que es "azúcar sintáctico" reemplazando dos métodos diferentes con nombres diferentes, siempre que el programador "conozca" el tipo estático y podría usar el nombre de método correcto en lugar del nombre sobrecargado. Es también una forma de polimorfismo estático, pero en forma limitada que normalmente no es muy potente.
Por supuesto, sería una molestia tener que cambiar los nombres de los métodos que llama cada vez que cambia el tipo de una variable, pero, por ejemplo, en el lenguaje C se considera una molestia manejable, por lo que C no tiene una sobrecarga de funciones (aunque ahora tiene macros genéricas).
En las plantillas de C ++, y en cualquier lenguaje que haga una deducción de tipo estático no trivial, realmente no puede argumentar que esto es "azúcar sintáctico" a menos que también argumente que la deducción de tipo estático es "azúcar sintáctico". Sería una molestia no tener plantillas, y en el contexto de C ++ sería una "molestia inmanejable", ya que son tan idiotas para el lenguaje y sus bibliotecas estándar. Entonces, en C ++ es más que un buen ayudante, es importante para el estilo del lenguaje, y creo que hay que llamarlo más que "azúcar sintáctico".
En Java, podría considerarlo más que una simple conveniencia considerando, por ejemplo, cuántas sobrecargas hay de
PrintStream.print
yPrintStream.println
. Pero entonces, hay tantosDataInputStream.readX
métodos ya que Java no se sobrecarga en el tipo de retorno, por lo que, en cierto sentido, es solo por conveniencia. Esos son todos para tipos primitivos.No recuerdo lo que ocurre en Java si tengo clases
A
yB
que se extiendeO
, sobrecargo métodosfoo(O)
,foo(A)
yfoo(B)
, a continuación, en un genérico con<T extends O>
que llamofoo(t)
, dondet
es una instancia deT
. En el caso en queT
esA
Cómo llego envío basado en la sobrecarga o se trata como si llamarafoo(O)
?Si es lo primero, entonces las sobrecargas del método Java son mejores que el azúcar de la misma manera que las sobrecargas de C ++. Usando su definición, supongo que en Java podría escribir localmente una serie de verificaciones de tipo (lo que sería frágil, porque las nuevas sobrecargas
foo
requerirían verificaciones adicionales). Además de aceptar esa fragilidad, no puedo hacer un cambio local en el sitio de la llamada para hacerlo bien; en cambio, tendría que renunciar a escribir código genérico. Yo diría que prevenir el código hinchado podría ser un azúcar sintáctico, pero prevenir el código frágil es más que eso. Por esa razón, el polimorfismo estático en general es más que solo azúcar sintáctico. La situación en un idioma en particular puede ser diferente, dependiendo de qué tan lejos el idioma le permita llegar al "no conocer" el tipo estático.fuente
T:Animal
es es escribirSiameseCat
y sobrecargas existentesCat Foo(Animal)
,SiameseCat Foo(Cat)
yAnimal Foo(SiameseCat)
, lo que sobrecarga deben seleccionarse siT
esSiameseCat
?long foo=Math.round(bar*1.0001)*5
se cambia along foo=Math.round(bar)*5
. ¿Cómo afectaría eso a la semántica sibar
es igual, por ejemplo, 123456789L?long
adouble
.double
¿ A ?Parece que el "azúcar sintáctico" suena despectivo, como inútil o frívolo. Es por eso que la pregunta desencadena muchas respuestas negativas.
Pero tiene razón, la sobrecarga de métodos no agrega ninguna característica al idioma, excepto la posibilidad de usar el mismo nombre para diferentes métodos. Puede hacer explícito el tipo de parámetro, el programa seguirá funcionando igual.
Lo mismo se aplica a los nombres de paquetes. La cadena es solo azúcar sintáctica para java.lang.String.
De hecho, un método como
en la clase MyClass debería llamarse algo así como "my_package_MyClass_fun_int_java_lang_String". Esto identificaría el método de manera única. (La JVM hace algo así internamente). Pero no quieres escribir eso. Es por eso que el compilador le permitirá escribir diversión (1, "uno") e identificar qué método es.
Sin embargo, hay una cosa que puede hacer con la sobrecarga: si sobrecarga un método con el mismo número de argumentos, el compilador descubrirá automáticamente qué versión se adapta mejor al argumento dado por argumentos coincidentes, no solo con tipos iguales, sino también donde El argumento dado es una subclase del argumento declarado.
Si tienes dos procedimientos sobrecargados
no necesita saber que existe una versión específica del procedimiento para las fechas. addParameter ("hello", "world) llamará a la primera versión, addParameter (" now ", new Date ()) llamará a la segunda.
Por supuesto, debe evitar sobrecargar un método con otro método que haga algo completamente diferente.
fuente
Curiosamente, la respuesta a esta pregunta dependerá del idioma.
Específicamente, existe una interacción entre la sobrecarga y la programación genérica. (*), y dependiendo de cómo se implemente la programación genérica, podría ser solo azúcar sintáctica (Rust) o absolutamente necesaria (C ++).
Es decir, cuando la programación genérica se implementa con interfaces explícitas (en Rust o Haskell, esas serían clases de tipo), la sobrecarga es simplemente azúcar sintáctica; o incluso podría no ser parte del lenguaje.
Por otro lado, cuando la programación genérica se implementa con tipificación de pato (ya sea dinámico o estático), el nombre del método es un contrato esencial y, por lo tanto, la sobrecarga es obligatoria para que el sistema funcione.
(*) Utilizado en el sentido de escribir un método una vez, para operar sobre varios tipos de manera uniforme.
fuente
En algunos idiomas, sin duda, es simplemente azúcar sintáctico. Sin embargo, lo que es un azúcar depende de su punto de vista. Dejaré esta discusión para más adelante en esta respuesta.
Por ahora me gustaría señalar que en algunos idiomas ciertamente no es azúcar sintáctica. Al menos no sin requerir que uses una lógica / algoritmo completamente diferente para implementar lo mismo. Es como afirmar que la recursividad es azúcar sintáctica (que es porque puedes escribir todo el algoritmo recursivo con un bucle y una pila).
Un ejemplo de uso muy difícil de reemplazar proviene de un lenguaje que, irónicamente, no llama a esta característica "sobrecarga de funciones". En cambio, se llama "coincidencia de patrones" (que puede verse como un superconjunto de sobrecarga porque podemos sobrecargar no solo los tipos sino los valores).
Aquí está la implementación ingenua clásica de la función Fibonacci en Haskell:
Podría decirse que las tres funciones se pueden reemplazar con un if / else como se hace comúnmente en cualquier otro idioma. Pero eso hace que la definición sea completamente simple:
mucho más desordenado y no expresa directamente la noción matemática de la secuencia de Fibonacci.
Entonces, a veces puede ser azúcar de sintaxis si el único uso es permitirle llamar a una función con diferentes argumentos. Pero a veces es mucho más fundamental que eso.
Ahora para la discusión de para qué operador la sobrecarga puede ser un azúcar. Ha identificado un caso de uso: puede usarse para implementar funciones similares que toman diferentes argumentos. Entonces:
alternativamente se puede implementar como:
o incluso:
Pero la sobrecarga del operador también puede ser un azúcar para implementar argumentos opcionales (algunos idiomas tienen sobrecarga del operador pero no argumentos opcionales):
puede usarse para implementar:
En dicho lenguaje ("lenguaje Ferite" de Google), eliminar la sobrecarga del operador elimina drásticamente una característica: los argumentos opcionales. Concedido en lenguajes con ambas características (c ++) eliminar uno u otro no tendrá ningún efecto neto ya que cualquiera de ellos puede usarse para implementar argumentos opcionales.
fuente
data PaymentInfo = CashOnDelivery | Adress String | UserInvoice CustomerInfo
que puede hacer coincidir patrones en los constructores de tipos.getPayment :: PaymentInfo -> a
getPayment CashOnDelivery = error "Should have been paid already"
getPayment (Adress addr) = -- code to notify administration to send a bill
getPayment (UserInvoice cust) = --whatever. I took the data type from a Haskell tutorial and have no idea what an invoice is
. Espero que este comentario sea algo comprensible.Creo que es el azúcar sintáctico simple en la mayoría de los idiomas (al menos todo lo que sé ...) ya que todos requieren una llamada de función sin ambigüedad en el momento de la compilación. Y el compilador simplemente reemplaza la llamada a la función con un puntero explícito a la firma de implementación correcta.
Ejemplo en Java:
Entonces, al final, podría reemplazarse completamente por una simple macro compiladora con buscar y reemplazar, reemplazando Function mangle sobrecargado con mangle_String y mangle_int, ya que la lista de argumentos es parte del eventual identificador de función, esto es prácticamente lo que sucede -> y por lo tanto, es solo azúcar sintáctico.
Ahora, si hay un lenguaje, donde la función está realmente determinada en tiempo de ejecución, como con los Métodos anulados en los objetos, esto sería diferente. Pero no creo que haya tal lenguaje, ya que method.overloading es propenso a la ambigüedad, que el compilador no puede resolver y que el programador debe manejar con un reparto explícito. Esto no se puede hacer en tiempo de ejecución.
fuente
En Java, la información de tipo se compila y cuál de las sobrecargas se llama se decide en el momento de la compilación.
El siguiente es un fragmento de
sun.misc.Unsafe
(la utilidad para Atomics) como se ve en el editor de archivos de clase de Eclipse.como puede ver, la información de tipo del método que se llama (línea 4) se incluye en la llamada.
Esto significa que podría crear un compilador de Java que tome información de tipo. Por ejemplo, utilizando una notación de este tipo, la fuente anterior sería:
y el elenco a largo sería opcional.
En otros lenguajes compilados de tipo estático, verá una configuración similar en la que el compilador decidirá qué sobrecarga se llamará según los tipos y la incluirá en el enlace / llamada.
La excepción son las bibliotecas dinámicas de C donde la información de tipo no está incluida y el intentar crear una función sobrecargada hará que el vinculador se queje.
fuente