Em vez de suportar a sobrecarga de métodos, o Ruby substitui os métodos existentes. Alguém pode explicar por que o idioma foi projetado dessa maneira?
146
A sobrecarga de método pode ser alcançada declarando dois métodos com o mesmo nome e assinaturas diferentes. Essas assinaturas diferentes podem ser,
method(int a, int b) vs method(String a, String b)
method(a) vs method(a, b)
Não é possível obter sobrecarga de método usando a primeira maneira, porque não há declaração de tipo de dados no ruby ( linguagem de tipo dinâmica ). Portanto, a única maneira de definir o método acima édef(a,b)
Com a segunda opção, pode parecer que podemos obter sobrecarga de método, mas não podemos. Digamos que eu tenha dois métodos com número diferente de argumentos,
def method(a); end;
def method(a, b = true); end; # second argument has a default value
method(10)
# Now the method call can match the first one as well as the second one,
# so here is the problem.
Portanto, o ruby precisa manter um método na cadeia de pesquisa de métodos com um nome exclusivo.
"Sobrecarregar" é um termo que simplesmente nem faz sentido no Ruby. É basicamente um sinónimo de "expedição à base de argumento estático", mas Ruby não têm expedição estática em tudo . Portanto, o motivo pelo qual o Ruby não suporta despacho estático com base nos argumentos é porque não suporta despacho estático, ponto final. Ele não suporta envio estático de qualquer tipo , seja com base em argumentos ou de outra forma.
Agora, se você não está perguntando especificamente sobre sobrecarga, mas talvez sobre despacho dinâmico baseado em argumentos, a resposta é: porque Matz não o implementou. Porque ninguém mais se incomodou em propor. Porque ninguém mais se preocupou em implementá-lo.
Em geral, o envio dinâmico baseado em argumentos em uma linguagem com argumentos opcionais e listas de argumentos de comprimento variável é muito difícil de acertar e ainda mais difícil de manter compreensível. Mesmo em linguagens com despacho estático baseado em argumentos e sem argumentos opcionais (como Java, por exemplo), às vezes é quase impossível dizer para um mero mortal, qual sobrecarga será detectada.
No C #, você pode realmente codificar qualquer problema 3-SAT na resolução de sobrecarga, o que significa que a resolução de sobrecarga no C # é NP-difícil.
Agora tente isso com despacho dinâmico , onde você tem a dimensão de tempo adicional para se lembrar.
Existem linguagens que são enviadas dinamicamente com base em todos os argumentos de um procedimento, em oposição às linguagens orientadas a objetos, que são enviadas apenas no
self
argumento zeroth "oculto" . O Lisp comum, por exemplo, despacha os tipos dinâmicos e até os valores dinâmicos de todos os argumentos. Clojure despacha em uma função arbitrária de todos os argumentos (que BTW é extremamente legal e extremamente poderoso).Mas não conheço nenhuma linguagem OO com despacho dinâmico baseado em argumentos. Martin Odersky disse que pode considerar adicionar expedição baseada em argumento ao Scala, mas apenas se ele puder remover a sobrecarga ao mesmo tempo e for compatível com versões anteriores, tanto com o código Scala existente que usa sobrecarga e compatível com Java (ele mencionou especialmente Swing e AWT que desempenham alguns truques extremamente complexos, exercitando praticamente todos os casos desagradáveis do canto escuro das regras de sobrecarga bastante complexas do Java). Eu mesmo tive algumas idéias sobre como adicionar expedição baseada em argumento ao Ruby, mas nunca consegui descobrir como fazê-lo de uma maneira compatível com versões anteriores.
fonte
def method(a, b = true)
não funcionará, portanto, a sobrecarga de método é impossível". Não é; é apenas difícil. Achei ESTA resposta realmente informativa, no entanto.Presumo que você esteja procurando a capacidade de fazer isso:
O Ruby suporta isso de uma maneira diferente:
Um padrão comum também é passar opções como um hash:
espero que ajude
fonte
A sobrecarga de método faz sentido em um idioma com digitação estática, onde você pode distinguir entre diferentes tipos de argumentos
bem como entre diferentes números de argumentos
A primeira distinção não existe no rubi. Ruby usa digitação dinâmica ou "digitação de pato". A segunda distinção pode ser tratada por argumentos padrão ou trabalhando com argumentos:
fonte
Isso não responde à pergunta de por que o ruby não possui sobrecarga de método, mas as bibliotecas de terceiros podem fornecê-lo.
A biblioteca contract.ruby permite sobrecarga. Exemplo adaptado do tutorial:
Observe que isso é realmente mais poderoso que a sobrecarga do Java, porque você pode especificar valores para corresponder (por exemplo
1
), não apenas tipos.Você verá um desempenho reduzido usando isso; você precisará executar benchmarks para decidir quanto pode tolerar.
fonte
Costumo fazer a seguinte estrutura:
Isso permite que o usuário do objeto use o método limpo e claro method_name: method Mas se ele deseja otimizar a execução, ele pode chamar diretamente o método correto.
Além disso, torna os testes mais claros e melhores.
fonte
já existem ótimas respostas sobre por que lado da questão. no entanto, se alguém que procura outras soluções, compra a gema de rubi funcional, inspirada nos recursos de correspondência de padrões do Elixir .
fonte