Sobrecarga de funções

Da Wikipédia, a enciclopédia livre
Ir para a navegação Saltar para pesquisar

Em algumas linguagens de programação , sobrecarga de função ou sobrecarga de método é a capacidade de criar várias funções com o mesmo nome com implementações diferentes. As chamadas para uma função sobrecarregada executarão uma implementação específica dessa função apropriada ao contexto da chamada, permitindo que uma chamada de função execute tarefas diferentes dependendo do contexto.

Por exemplo, doTask() e doTask(object o) são funções sobrecarregadas. Para chamar o último, um objeto deve ser passado como parâmetro , enquanto o primeiro não requer um parâmetro e é chamado com um campo de parâmetro vazio. Um erro comum seria atribuir um valor padrão ao objeto na segunda função, o que resultaria em um erro de chamada ambíguo , pois o compilador não saberia qual dos dois métodos usar.

Outro exemplo é uma função Print(object o) que executa diferentes ações com base na impressão de texto ou fotos. As duas funções diferentes podem ser sobrecarregadas como Print(text_object T); Print(imagem_objeto P) . Se escrevermos as funções de impressão sobrecarregadas para todos os objetos que nosso programa irá "imprimir", nunca teremos que nos preocupar com o tipo do objeto, e a chamada de função correta novamente, a chamada é sempre: Print(something) .

Idiomas que suportam sobrecarga

Os idiomas que suportam sobrecarga de função incluem, mas não estão necessariamente limitados ao seguinte:

Regras na sobrecarga de funções

  • O mesmo nome de função é usado para mais de uma definição de função
  • As funções devem diferir pela aridade ou pelos tipos de seus parâmetros

É uma classificação de polimorfismo estático em que uma chamada de função é resolvida usando algum algoritmo de "melhor correspondência", em que a função específica a ser chamada é resolvida encontrando a melhor correspondência dos tipos de parâmetros formais com os tipos de parâmetros reais. Os detalhes desse algoritmo variam de idioma para idioma.

A sobrecarga de função geralmente está associada a linguagens de programação com tipagem estática que impõem a verificação de tipo em chamadas de função . Uma função sobrecarregada é realmente apenas um conjunto de funções diferentes que têm o mesmo nome. A determinação de qual função usar para uma chamada específica é resolvida em tempo de compilação .

Em Java , a sobrecarga de função também é conhecida como polimorfismo em tempo de compilação e polimorfismo estático.

A sobrecarga de funções não deve ser confundida com formas de polimorfismo em que a escolha é feita em tempo de execução, por exemplo, por meio de funções virtuais , em vez de estaticamente.

Exemplo: sobrecarga de funções em C++

#include <iostream> 

int Volume ( int s ) { // Volume de um cubo. retorna s * s * s ;     
       
}

double Volume ( double r , int h ) { // Volume de um cilindro. return 3.1415926 * r * r * static_cast < double > ( h );       
         
}

long Volume ( long l , int b , int h ) { // Volume de um paralelepípedo. retorne l * b * h ;         
       
}

int main () {  
  std :: cout << Volume ( 10 );  
  std :: cout << Volume ( 2,5 , 8 );   
  std :: cout << Volume ( 100l , 75 , 15 );    
}

No exemplo acima, o volume de cada componente é calculado usando uma das três funções denominadas "volume", com seleção baseada no número e tipo diferentes de parâmetros reais.

Sobrecarga do construtor

Construtores , usados ​​para criar instâncias de um objeto, também podem ser sobrecarregados em algumas linguagens de programação orientadas a objetos . Como em muitas linguagens o nome do construtor é predeterminado pelo nome da classe, parece que pode haver apenas um construtor. Sempre que vários construtores são necessários, eles devem ser implementados como funções sobrecarregadas. Em C++ , os construtores padrão não aceitam parâmetros, instanciando os membros do objeto com seus valores padrão apropriados, "que normalmente é zero para campos numerais e string vazia para campos de string". [5] Por exemplo, um construtor padrão para um objeto de conta de restaurante escrito em C++ pode definir a dica para 15%:

Conta ()
    : dica ( 0,15 ), // porcentagem total ( 0,0 )  
      
{ } 

A desvantagem disso é que são necessárias duas etapas para alterar o valor do objeto Bill criado. O seguinte mostra a criação e alteração dos valores dentro do programa principal:

Café da conta ; 
café . ponta = 0,10 ;  
café . total = 4,00 ;  

Ao sobrecarregar o construtor, pode-se passar a dica e o total como parâmetros na criação. Isso mostra o construtor sobrecarregado com dois parâmetros. Esse construtor sobrecarregado é colocado na classe, assim como o construtor original que usamos antes. Qual deles é usado depende do número de parâmetros fornecidos quando o novo objeto Bill é criado (nenhum ou dois):

Bill ( ponta dupla , total duplo )   
    : ponta ( ponta ), 
      total ( total )
{ } 

Agora, uma função que cria um novo objeto Bill pode passar dois valores para o construtor e definir os membros de dados em uma etapa. Veja a seguir a criação e a configuração dos valores:

Bill café ( 0,10 , 4,00 );  

Isso pode ser útil para aumentar a eficiência do programa e reduzir o comprimento do código.

Outro motivo para a sobrecarga do construtor pode ser impor membros de dados obrigatórios. Nesse caso, o construtor padrão é declarado privado ou protegido (ou preferencialmente excluído desde C++ 11 ) para torná-lo inacessível de fora. Para o Bill acima, o total pode ser o único parâmetro do construtor – já que um Bill não tem um padrão sensato para o total – enquanto o padrão de dica é 0,15.

Complicações

Dois problemas interagem e complicam a sobrecarga de função: mascaramento de nome (devido ao scope ) e conversão de tipo implícita .

Se uma função for declarada em um escopo e, em seguida, outra função com o mesmo nome for declarada em um escopo interno, haverá dois comportamentos naturais de sobrecarga possíveis: a declaração interna mascara a declaração externa (independentemente da assinatura) ou ambas a declaração interna e a declaração externa são incluídas na sobrecarga, com a declaração interna mascarando a declaração externa somente se a assinatura corresponder. A primeira é tirada em C++: "em C++, não há sobrecarga nos escopos". [6] Como resultado, para obter um conjunto de sobrecarga com funções declaradas em escopos diferentes, é preciso importar explicitamente as funções do escopo externo para o escopo interno, com a palavra- usingchave.

A conversão de tipo implícita complica a sobrecarga de função porque se os tipos de parâmetros não corresponderem exatamente à assinatura de uma das funções sobrecarregadas, mas puderem corresponder após a conversão de tipo, a resolução dependerá de qual conversão de tipo for escolhida.

Eles podem se combinar de maneiras confusas: uma correspondência inexata declarada em um escopo interno pode mascarar uma correspondência exata declarada em um escopo externo, por exemplo. [6]

Por exemplo, para ter uma classe derivada com uma função sobrecarregada pegando um doubleou um int, usando a função pegando um intda classe base, em C++, escreveríamos:

classe  B { 
 público :
  vazio F ( int i );  
};

classe  D : público B {    
 público :
  usando B :: F ; 
  vazio F ( duplo d );  
};

Falha ao incluir os usingresultados em um intparâmetro passado para Fa classe derivada que está sendo convertida em um double e correspondendo à função na classe derivada, em vez da classe base; A inclusão usingresulta em uma sobrecarga na classe derivada e, portanto, corresponde à função na classe base.

Advertências

Se um método for projetado com um número excessivo de sobrecargas, pode ser difícil para os desenvolvedores discernir qual sobrecarga está sendo chamada simplesmente lendo o código. Isso é particularmente verdadeiro se alguns dos parâmetros sobrecarregados forem de tipos herdados de outros parâmetros possíveis (por exemplo, "objeto"). Um IDE pode executar a resolução de sobrecarga e exibir (ou navegar para) a sobrecarga correta.

A sobrecarga baseada em tipo também pode dificultar a manutenção do código, onde as atualizações de código podem alterar acidentalmente qual sobrecarga de método é escolhida pelo compilador. [7]

Veja também

Referências

  1. ^ "Especificação da linguagem Kotlin" . kotlinlang.org .
  2. ^ "37.6. Sobrecarga de funções" . Documentação do PostgreSQL . 2021-08-12 . Recuperado 2021-08-29 .
  3. ^ "Guia e referência do usuário do banco de dados PL/SQL" . docs.oracle.com . Recuperado 2021-08-29 .
  4. ^ "Manual do Nim" . nim-lang.org .
  5. ^ Chan, Jamie (2017). Aprenda C# em um dia e aprenda bem (edição revisada). pág. 82. ISBN 978-1518800276.
  6. ^ a b Stroustrup, Bjarne . "Por que a sobrecarga não funciona para classes derivadas?" .
  7. ^ Bracha, Gilad (3 de setembro de 2009). "Sobrecarga Sistêmica" . Sala 101.

Links externos