O método sobrecarrega um tipo de polimorfismo? Para mim, parece simplesmente a diferenciação de métodos com o mesmo nome e parâmetros diferentes. Portanto, stuff(Thing t)
e stuff(Thing t, int n)
são métodos totalmente diferentes no que diz respeito ao compilador e ao tempo de execução.
Cria a ilusão, do lado do interlocutor, de que é o mesmo método que age de maneira diferente em diferentes tipos de objetos - polimorfismo. Mas isso é apenas uma ilusão, porque na verdade stuff(Thing t)
e stuff(Thing t, int n)
são métodos completamente diferentes.
A sobrecarga de método é algo além de açúcar sintático? Estou esquecendo de algo?
Uma definição comum para o açúcar sintático é que é puramente local . Significar alterar um pedaço de código para seu equivalente "adocicado", ou vice-versa, envolve mudanças locais que não afetam a estrutura geral do programa. E acho que a sobrecarga de método se encaixa exatamente nesse critério. Vejamos um exemplo para demonstrar:
Considere uma classe:
class Reader {
public String read(Book b){
// .. translate the book to text
}
public String read(File b){
// .. translate the file to text
}
}
Agora considere outra classe que usa essa classe:
/* 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
}
}
OK. Agora vamos ver o que precisa ser alterado se substituirmos a sobrecarga do método por métodos regulares:
Os read
métodos em Reader
mudança para readBook(Book)
e readFile(file)
. Apenas uma questão de mudar seus nomes.
O código de chamada FileProcessor
muda um pouco: reader.read(file)
muda para reader.readFile(file)
.
E é isso.
Como você pode ver, a diferença entre usar sobrecarga de método e não usá-lo é puramente local . E é por isso que acho que se qualifica como puro açúcar sintático.
Gostaria de ouvir suas objeções, se você tiver alguma, talvez esteja perdendo alguma coisa.
fonte
Respostas:
Para responder a isso, primeiro você precisa de uma definição para "açúcar sintático". Eu vou com a Wikipedia :
Portanto, sob essa definição, recursos como os varargs de Java ou a compreensão de Scala são açúcar sintático: eles se traduzem em recursos de linguagem subjacentes (uma matriz no primeiro caso, chamadas para mapear / flatmap / filtro no segundo) e removê-los Não mude as coisas que você pode fazer com o idioma.
A sobrecarga de método, no entanto, não é um açúcar sintático nesta definição, porque removê-la mudaria fundamentalmente o idioma (você não seria mais capaz de enviar para um comportamento distinto com base em argumentos).
É verdade que você pode simular a sobrecarga do método, desde que tenha alguma maneira de acessar os argumentos de um método, e pode usar uma construção "se" com base nos argumentos fornecidos. Mas se você considerar esse açúcar sintático, teria que considerar qualquer coisa acima de uma máquina de Turing para ser igualmente açúcar sintático.
fonte
sum(numbersArray)
e emsum(numbersList)
vez desumArray(numbersArray)
esumList(numbersList)
. Eu concordo com Doval, parece mero açúcar sintático.instanceof
, classes, herança, interfaces genéricos, reflexão ou especificadores de acesso que utilizamif
,while
e operadores booleanos, com exatamente a mesma semântica . Não há esquinas. Observe que não estou desafiando você a calcular as mesmas coisas que os usos específicos dessas construções. Eu já sei que você pode calcular qualquer coisa usando lógica booleana e ramificação / loop. Eu estou pedindo para você implementar cópias perfeitas dos semântica desses recursos de linguagem, incluindo quaisquer garantias estáticos que eles fornecem (cheques tempo de compilação ainda deve ser feito em tempo de compilação.)O termo açúcar sintático geralmente se refere aos casos em que o recurso é definido por uma substituição. A linguagem não define o que um recurso faz; em vez disso, define que é exatamente equivalente a outra coisa. Por exemplo, para cada loop
Torna-se:
Ou use uma função com argumentos variáveis:
O que se torna:
Portanto, há uma substituição trivial da sintaxe para implementar o recurso em termos de outros recursos.
Vejamos a sobrecarga do método.
Isso pode ser reescrito como:
Mas não é equivalente a isso. Dentro do modelo de Java, isso é algo diferente.
foo(int a)
não implementa umafoo_int
função a ser criada. Java não implementa a sobrecarga de método, dando nomes engraçados às funções ambíguas. Para contar como açúcar sintático, o java teria que estar fingindo que você realmente escreveufoo_int
efoo_double
funciona, mas não funciona.fonte
But, the transformation isn't trivial. At the least, you have to determine the types of the parameters.
muito superficial, porque os tipos não precisam ser determinados ; eles são conhecidos em tempo de compilação.foo(int)
/foo(double)
efoo_int
/foo_double
? Eu realmente não conheço Java muito bem, mas imagino que essa renomeação realmente aconteça na JVM (bem - provavelmente usandofoo(args)
mais do que issofoo_args
- acontece pelo menos em C ++ com manipulação de símbolos (ok - a manipulação de símbolos é tecnicamente um detalhe de implementação e não faz parte) da linguagem).for
loop aprimorado não é mais expressivo que Java sem ele. (É mais agradável, mais conciso, mais legível e, em geral, melhor, eu diria, mas não mais expressivo.) Mas não tenho certeza sobre o caso de sobrecarga. Provavelmente terei que reler o artigo para ter certeza. Meu intestino diz que é açúcar sintático, mas não tenho certeza.Dado que a mudança de nome funciona, não precisa ser nada além de açúcar sintático?
Permite ao chamador imaginar que está chamando a mesma função, quando não está. Mas ele sabia os nomes reais de todas as suas funções. Somente se fosse possível obter um polimorfismo atrasado passando uma variável não digitada para uma função digitada e tendo seu tipo estabelecido para que a chamada pudesse ir para a versão correta de acordo com o nome, esse seria um recurso de linguagem real.
Infelizmente, nunca vi um idioma fazer isso. Quando há ambiguidade, esses compiladores não a resolvem, eles insistem em que o escritor a resolva por eles.
fonte
dynamic
, a resolução de sobrecarga ocorrerá no tempo de execução, não no tempo de compilação . É isso que é o despacho múltiplo e não pode ser replicado renomeando funções.Dependendo do idioma, é açúcar sintático ou não.
No C ++, por exemplo, você pode fazer coisas usando sobrecarga e modelos, o que não seria possível sem complicações (escreva manualmente todas as instâncias do modelo ou adicione muitos parâmetros).
Observe que o despacho dinâmico é uma forma de sobrecarga, resolvida dinamicamente em alguns parâmetros (para alguns idiomas apenas um especial, este , mas nem todos os idiomas são tão limitados), e eu não chamaria essa forma de sobrecarga de açúcar sintático.
fonte
Para idiomas contemporâneos, é apenas açúcar sintático; de uma maneira completamente independente da linguagem, é mais do que isso.
Anteriormente, essa resposta dizia simplesmente que é mais do que açúcar sintático, mas se você ver nos comentários, Falco levantou a questão de que havia uma peça do quebra-cabeça que as línguas contemporâneas parecem estar faltando; eles não misturam sobrecarga de método com determinação dinâmica de qual função chamar na mesma etapa. Isso será esclarecido mais tarde.
Aqui é por isso que deve haver mais.
Considere uma linguagem que suporte sobrecarga de método e variáveis não tipadas. Você pode ter os seguintes protótipos de método:
Em alguns idiomas, você provavelmente se resignaria a saber, em tempo de compilação, qual deles seria chamado por uma determinada linha de código. Mas em alguns idiomas, nem todas as variáveis são digitadas (ou todas implicitamente digitadas como
Object
ou o que for), então imagine criar um dicionário cujas chaves sejam mapeadas para valores de diferentes tipos:Agora, então, e se você quisesse aplicar
someFunction
a um desses números de quarto? Você chama isso:É
someFunction(int)
chamado ou ésomeFunction(string)
chamado? Aqui você vê um exemplo em que esses métodos não são totalmente ortogonais, especialmente em idiomas de nível superior. A linguagem precisa descobrir - durante o tempo de execução - qual delas chamar, por isso ainda precisa considerá-las como sendo pelo menos um pouco o mesmo método.Por que não simplesmente usar modelos? Por que não usar simplesmente um argumento não digitado?
Flexibilidade e controle mais refinado. Às vezes, usar modelos / argumentos sem tipo é uma abordagem melhor, mas às vezes não.
Você deve pensar nos casos em que, por exemplo, você pode ter duas assinaturas de método que usam cada um
int
e astring
como argumentos, mas onde a ordem é diferente em cada assinatura. Você pode muito bem ter um bom motivo para fazer isso, pois a implementação de cada assinatura pode fazer basicamente a mesma coisa, mas com um toque um pouco diferente; o registro pode ser diferente, por exemplo. Ou mesmo se eles fizerem exatamente a mesma coisa, você poderá coletar automaticamente determinadas informações apenas pela ordem em que os argumentos foram especificados. Tecnicamente, você pode usar apenas instruções pseudo-switch para determinar o tipo de cada um dos argumentos passados, mas isso fica confuso.Então, este próximo exemplo é uma prática ruim de programação?
Sim, em geral. Neste exemplo em particular, isso poderia impedir alguém de aplicar isso a certos tipos primitivos e recuperar comportamentos inesperados (o que poderia ser uma coisa boa); mas vamos supor que eu abreviei o código acima e que você, de fato, possui sobrecargas para todos os tipos primitivos, bem como para
Object
s. Então este próximo pedaço de código é realmente mais apropriado:Mas e se você só precisava usar isso para
int
s estring
s, e se você quer que ele retornar verdadeiro com base em condições mais simples ou mais complicado nesse sentido? Então você tem um bom motivo para usar a sobrecarga:Mas ei, por que não dar a essas funções dois nomes diferentes? Você ainda tem a mesma quantidade de controle refinado, não é?
Porque, como afirmado anteriormente, alguns hotéis usam números, alguns usam letras e alguns usam uma mistura de números e letras:
Este ainda não é exatamente o mesmo código exato que eu usaria na vida real, mas deve ilustrar o ponto que estou fazendo bem.
Mas ... Eis por que não é mais que açúcar sintático nas línguas contemporâneas.
Falco levantou a questão nos comentários de que os idiomas atuais basicamente não combinam sobrecarga de método e seleção dinâmica de função na mesma etapa. A maneira como eu entendi anteriormente que certas linguagens funcionavam era que você poderia sobrecarregar
appearsToBeFirstFloor
no exemplo acima e, em seguida, a linguagem determinaria em tempo de execução qual versão da função seria chamada, dependendo do valor em tempo de execução da variável não digitada. Essa confusão resultou parcialmente do trabalho com tipos de linguagens ECMA, como o ActionScript 3.0, no qual você pode facilmente randomizar qual função é chamada em uma determinada linha de código em tempo de execução.Como você deve saber, o ActionScript 3 não suporta sobrecarga de métodos. Quanto ao VB.NET, você pode declarar e definir variáveis sem atribuir um tipo explicitamente, mas ao tentar passar essas variáveis como argumentos para métodos sobrecarregados, ele ainda não deseja ler o valor do tempo de execução para determinar qual método chamar; em vez disso, deseja encontrar um método com argumentos do tipo
Object
ou nenhum tipo ou algo assim. Portanto, o exemploint
vs.string
acima também não funcionaria nesse idioma. O C ++ tem problemas semelhantes, pois quando você usa algo como um ponteiro nulo ou algum outro mecanismo como esse, ainda é necessário desambiguar manualmente o tipo em tempo de compilação.Então, como o primeiro cabeçalho diz ...
Para idiomas contemporâneos, é apenas açúcar sintático; de uma maneira completamente independente da linguagem, é mais do que isso. Tornar a sobrecarga de método mais útil e relevante, como no exemplo acima, pode realmente ser um bom recurso para adicionar a um idioma existente (como tem sido amplamente implicitamente solicitado para o AS3), ou também pode servir como um entre muitos pilares fundamentais diferentes para a criação de uma nova linguagem processual / orientada a objetos.
fonte
this[chooseFunctionNameAtRandom]();
SechooseFunctionNameAtRandom()
retornos tanto"punch"
,"kick"
ou"dodge"
, então você pode thusly implementar uma forma muito simples aleatória elemento em, por exemplo, a IA de um inimigo em um jogo em Flash.Realmente depende da sua definição de "açúcar sintático". Vou tentar abordar algumas das definições que me vêm à mente:
Um recurso é um açúcar sintático quando um programa que o usa sempre pode ser traduzido em outro que não o usa.
Aqui estamos assumindo que existe um conjunto primitivo de recursos que não podem ser traduzidos: em outras palavras, não existem loops do tipo "você pode substituir o recurso X usando o recurso Y" e "você pode substituir o recurso Y pelo recurso X". Se um dos dois for verdadeiro, o outro recurso poderá ser expresso em termos de recursos que não são o primeiro ou é um recurso primitivo.
Igual à definição 1, mas com o requisito extra de que o programa traduzido seja tão seguro quanto o primeiro, ou seja, ao desugar você não perde nenhum tipo de informação.
A definição do OP: um recurso é o açúcar sintático se sua tradução não altera a estrutura do programa, mas requer apenas "alterações locais".
Vamos usar o Haskell como exemplo para sobrecarga. Haskell fornece sobrecarga definida pelo usuário através de classes de tipo. Por exemplo, as operações
+
e*
são definidas naNum
classe type e qualquer tipo que tenha uma instância (completa) dessa classe pode ser usada+
. Por exemplo:Uma coisa bem conhecida sobre as classes de tipo de Haskell é que você pode se livrar delas . Ou seja, você pode traduzir qualquer programa que utilize classes de tipos em um programa equivalente que não as utilize.
A tradução é bastante simples:
Dada uma definição de classe:
Você pode convertê-lo em um tipo de dados algébrico:
Aqui
X_P_i
eX_op_i
são seletores . Ou seja, dado um valor do tipo que seX a
aplicaX_P_1
ao valor, ele retornará o valor armazenado nesse campo, portanto, são funções com o tipoX a -> P_i a
(ouX a -> t_i
).Para uma anologia muito grosseira, você pode pensar nos valores para o tipo
X a
comostruct
se, em seguida, sex
for do tipo,X a
as expressões:pode ser visto como:
(É fácil usar apenas campos posicionais em vez de campos nomeados, mas os campos nomeados são mais fáceis de manipular nos exemplos e evitam algum código da placa da caldeira).
Dada uma declaração de instância:
Você pode convertê-lo em uma função que, devido aos dicionários das
C_1 a_1, ..., C_n a_n
classes, retorne um valor de dicionário (ou seja, um valor do tipoX a
) para o tipoT a_1 ... a_n
.Em outras palavras, a instância acima pode ser traduzida para uma função como:
(Observe que
n
pode ser0
).E, de fato, podemos defini-lo como:
onde
op_1 = ...
aop_m = ...
é a definição encontrada nainstance
declaração e oget_P_i_T
são as funções definidas peloP_i
exemplo doT
tipo (estas têm de existir porqueP_i
s são superclasses deX
).Dada uma chamada para uma função sobrecarregada:
Podemos passar explicitamente os dicionários relativos às restrições de classe e obter uma chamada equivalente:
Observe como as restrições de classe simplesmente se tornaram um novo argumento. O
+
programa traduzido é o seletor, conforme explicado anteriormente. Em outras palavras, aadd
função traduzida , dado o dicionário para o tipo de argumento, primeiro "descompactará" a função real para calcular o resultado usando(+) dictNum
e, em seguida, aplicará essa função aos argumentos.Este é apenas um esboço muito rápido sobre a coisa toda. Se você estiver interessado, leia os artigos de Simon Peyton Jones et al.
Acredito que uma abordagem semelhante também possa ser usada para sobrecarregar em outros idiomas.
No entanto, isso mostra que, se sua definição de açúcar sintático é (1), sobrecarregar é açúcar sintático . Porque você pode se livrar disso.
No entanto, o programa traduzido perde algumas informações sobre o programa original. Por exemplo, não impõe a existência de instâncias para as classes pai. (Mesmo que as operações para extrair os dicionários dos pais ainda devam ser desse tipo, você pode passar
undefined
valores polimórficos ou outros, para poder criar um valorX y
sem os valoresP_i y
, para que a tradução não perca tudo o tipo de segurança). Portanto, não é o açúcar sintático de acordo com (2)Quanto a (3). Não sei se a resposta deve ser sim ou não.
Eu diria que não, porque, por exemplo, uma declaração de instância se torna uma definição de função. As funções sobrecarregadas recebem um novo parâmetro (o que significa que altera a definição e todas as chamadas).
Eu diria que sim, porque os dois programas ainda mapeiam um para um, então a "estrutura" não é realmente muito alterada.
Dito isto, eu diria que as vantagens pragmáticas introduzidas pela sobrecarga são tão grandes que o uso de um termo "depreciativo" como "açúcar sintático" não parece correto.
Você pode traduzir toda a sintaxe Haskell para uma linguagem Core muito simples (que na verdade é feita durante a compilação); portanto, a maioria da sintaxe Haskell pode ser vista como "açúcar sintático" para algo que é apenas cálculo lambda e algumas novas construções. No entanto, podemos concordar que os programas Haskell são muito mais fáceis de manusear e são muito concisos, enquanto os programas traduzidos são muito mais difíceis de ler ou pensar.
fonte
Se a expedição for resolvida no tempo de compilação, dependendo apenas do tipo estático da expressão do argumento, você certamente poderá argumentar que é "açúcar sintático" substituindo dois métodos diferentes por nomes diferentes, desde que o programador "conheça" o tipo estático e poderia apenas usar o nome do método correto no lugar do nome sobrecarregado. É também uma forma de polimorfismo estático, mas nessa forma limitada geralmente não é muito poderosa.
É claro que seria um incômodo alterar os nomes dos métodos que você chama sempre que alterar o tipo de uma variável, mas, por exemplo, na linguagem C é considerado um incômodo gerenciável, portanto, C não possui sobrecarga de função (embora agora possui macros genéricas).
Nos modelos C ++ e em qualquer linguagem que deduza o tipo estático não trivial, não é possível argumentar que isso é "açúcar sintático", a menos que você também defenda que a dedução do tipo estático é "açúcar sintático". Seria um incômodo não ter modelos e, no contexto do C ++, seria um "incômodo incontrolável", pois eles são tão idiomáticos para a linguagem e suas bibliotecas padrão. Portanto, em C ++ é mais do que um bom ajudante, é importante para o estilo da linguagem e, portanto, acho que você deve chamá-la mais do que "açúcar sintático".
Em Java, você pode considerar isso mais do que apenas uma conveniência, considerando, por exemplo, quantas sobrecargas existem
PrintStream.print
ePrintStream.println
. Porém, existem tantosDataInputStream.readX
métodos, já que o Java não sobrecarrega no tipo de retorno; portanto, em certo sentido, é apenas por conveniência. Esses são todos para tipos primitivos.Não me lembro o que acontece em Java se eu tiver aulas
A
eB
estendendoO
, eu sobrecarregar métodosfoo(O)
,foo(A)
efoo(B)
, em seguida, em um genérico com<T extends O>
chamofoo(t)
ondet
é uma instância deT
. No caso em queT
éA
que eu ganho envio com base na sobrecarga ou é como se eu chamassefoo(O)
?No caso anterior, as sobrecargas do método Java são melhores que o açúcar, da mesma forma que as sobrecargas do C ++. Usando sua definição, suponho que em Java eu poderia escrever localmente uma série de verificações de tipo (que seriam frágeis, porque novas sobrecargas
foo
exigiriam verificações adicionais). Além de aceitar essa fragilidade, não posso fazer uma alteração local no site de chamada para acertar, em vez disso, teria que desistir de escrever código genérico. Eu argumentaria que a prevenção de códigos inchados pode ser um açúcar sintático, mas a prevenção de códigos frágeis é mais do que isso. Por esse motivo, o polimorfismo estático em geral é mais do que apenas açúcar sintático. A situação em um idioma específico pode ser diferente, dependendo de quão longe o idioma permita "não conhecer" o tipo estático.fonte
T:Animal
é é tipoSiameseCat
e sobrecargas existentesCat Foo(Animal)
,SiameseCat Foo(Cat)
eAnimal Foo(SiameseCat)
, que a sobrecarga deve ser selecionado seT
éSiameseCat
?long foo=Math.round(bar*1.0001)*5
seja alterada paralong foo=Math.round(bar)*5
. Como isso afetaria a semântica se fossebar
igual, por exemplo, 123456789L?long
paradouble
.double
?Parece que "açúcar sintático" soa depreciativo, como inútil ou frívolo. É por isso que a pergunta desencadeia muitas respostas negativas.
Mas você está certo, a sobrecarga de método não adiciona nenhum recurso ao idioma, exceto pela possibilidade de usar o mesmo nome para métodos diferentes. Você pode tornar o tipo de parâmetro explícito, o programa continuará funcionando da mesma forma.
O mesmo se aplica aos nomes dos pacotes. String é apenas açúcar sintático para java.lang.String.
De fato, um método como
na classe MyClass deve ser chamado algo como "my_package_MyClass_fun_int_java_lang_String". Isso identificaria o método exclusivamente. (A JVM faz algo assim internamente). Mas você não quer escrever isso. É por isso que o compilador permite que você escreva divertido (1, "um") e identifique qual é o método.
No entanto, há uma coisa que você pode fazer com a sobrecarga: se você sobrecarregar um método com o mesmo número de argumentos, o compilador descobrirá automaticamente qual versão se adapta melhor ao argumento fornecido pelos argumentos correspondentes, não apenas com tipos iguais, mas também onde o argumento fornecido é uma subclasse do argumento declarado.
Se você tiver dois procedimentos sobrecarregados
você não precisa saber que existe uma versão específica do procedimento para Datas. addParameter ("hello", "world) chamará a primeira versão, addParameter (" now ", new Date ()) chamará a segunda.
Obviamente, você deve evitar sobrecarregar um método com outro método que faça algo completamente diferente.
fonte
Curiosamente, a resposta a esta pergunta dependerá do idioma.
Especificamente, há uma interação entre sobrecarga e programação genérica (*) e, dependendo de como a programação genérica é implementada, pode ser apenas açúcar sintático (Rust) ou absolutamente necessário (C ++).
Ou seja, quando a programação genérica é implementada com interfaces explícitas (em Rust ou Haskell, essas seriam classes de tipo), a sobrecarga é apenas um açúcar sintático; ou, na verdade, talvez nem faça parte do idioma.
Por outro lado, quando a programação genérica é implementada com digitação de pato (seja dinâmica ou estática), o nome do método é um contrato essencial e, portanto, a sobrecarga é obrigatória para o sistema funcionar.
(*) Usado no sentido de escrever um método uma vez, para operar sobre vários tipos de maneira uniforme.
fonte
Em algumas línguas, é sem dúvida apenas o açúcar sintático. No entanto, o que é um açúcar depende do seu ponto de vista. Vou deixar essa discussão para mais adiante nesta resposta.
Por enquanto, gostaria de observar que, em alguns idiomas, certamente não é um açúcar sintático. Pelo menos não sem exigir que você use uma lógica / algoritmo completamente diferente para implementar a mesma coisa. É como afirmar que a recursão é um açúcar sintático (que é porque você pode escrever todo o algoritmo recursivo com um loop e uma pilha).
Um exemplo de uso muito difícil de substituir vem de uma linguagem que ironicamente não chama esse recurso de "sobrecarga de função". Em vez disso, é chamado de "correspondência de padrão" (que pode ser vista como um superconjunto de sobrecarga, porque podemos sobrecarregar não apenas tipos, mas valores).
Aqui está a implementação ingênua clássica da função Fibonacci em Haskell:
Indiscutivelmente, as três funções podem ser substituídas por um if / else, como geralmente é feito em qualquer outro idioma. Mas isso fundamentalmente torna a definição totalmente simples:
muito mais confuso e não expressa diretamente a noção matemática da sequência de Fibonacci.
Portanto, às vezes, pode ser açúcar de sintaxe, se o único uso é permitir que você chame uma função com argumentos diferentes. Mas, às vezes, é muito mais fundamental que isso.
Agora, vamos discutir o motivo pelo qual a sobrecarga do operador pode ser um açúcar. Você identificou um caso de uso - ele pode ser usado para implementar funções semelhantes que usam argumentos diferentes. Então:
Como alternativa, pode ser implementado como:
ou até:
Mas a sobrecarga do operador também pode ser uma ferramenta importante para implementar argumentos opcionais (alguns idiomas têm sobrecarga de operador, mas não argumentos opcionais):
pode ser usado para implementar:
Nessa linguagem (google "Ferite language"), a remoção de sobrecarga do operador remove drasticamente um recurso - argumentos opcionais. Concedido em idiomas com ambos os recursos (c ++), remover um ou outro não terá efeito líquido, pois ambos podem ser usados para implementar argumentos opcionais.
fonte
data PaymentInfo = CashOnDelivery | Adress String | UserInvoice CustomerInfo
você pode fazer a correspondência de padrões nos construtores 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 comentário seja um pouco compreensível.Eu acho que é um açúcar sintático simples na maioria dos idiomas (pelo menos tudo o que sei ...), pois todos eles exigem uma chamada de função inequívoca em tempo de compilação. E o compilador simplesmente substitui a chamada de função por um ponteiro explícito para a assinatura de implementação correta.
Exemplo em Java:
Portanto, no final, poderia ser completamente substituído por uma macro-compilador simples com pesquisa e substituição, substituindo a função sobrecarregada mangle por mangle_String e mangle_int - uma vez que a lista de argumentos faz parte do eventual identificador de função, é praticamente o que acontece -> e portanto, é apenas açúcar sintático.
Agora, se houver uma linguagem em que a função seja realmente determinada em tempo de execução, como nos Métodos substituídos nos objetos, isso seria diferente. Mas não creio que exista essa linguagem, já que method.overloading é propenso a ambiguidade, que o compilador não pode resolver e que deve ser tratado pelo programador com um elenco explícito. Isso não pode ser feito em tempo de execução.
fonte
No tipo Java, as informações são compiladas e qual das sobrecargas é chamada é decidida no momento da compilação.
A seguir, um trecho de
sun.misc.Unsafe
(o utilitário Atomics), conforme exibido no editor de arquivos de classe do Eclipse.como você pode ver as informações de tipo do método que está sendo chamado (linha 4) estão incluídas na chamada.
Isso significa que você pode criar um compilador java que usa informações de tipo. Por exemplo, usando essa notação, a fonte acima seria:
e o elenco para longo seria opcional.
Em outras linguagens compiladas estaticamente, você verá uma configuração semelhante em que o compilador decidirá qual sobrecarga será chamada dependendo dos tipos e a incluirá na ligação / chamada.
A exceção são as bibliotecas dinâmicas C, nas quais as informações de tipo não são incluídas e a tentativa de criar uma função sobrecarregada fará com que o vinculador reclame.
fonte