Polimorfismo de aparência
Reuso aparente, na prática não o faz
Subtipos
- Coerção
- Sobrecarga
Conversão implícita
- Alargamento
- Do conjunto mais restrito para o menos restrito
- Estreitamento
- Do conjunto menos restrito para o mais restrito
- Perda de informação
Exemplo de polimorfismo adhoc por coerção
void f(float i) { }
main() {
long num;
f(num);
}
- O subprograma
f()
é polimórfico?
Segundo exemplo de polimofirmo adhoc por coerção
main() {
int w = 3;
float x;
float y = 5.2;
x = x + y;
x = x + w;
}
O operador +
é polimórfico?
Onde ocorre polimorfismo aparente neste trecho em C?
1 main() {
2 int i;
3 char c = 'a';
4 float x;
5 i = c;
6 c = i + 1;
7 x = i;
8 i = x / 7;
9 }
Redigibilidade facilitada
Diminuem a confiabilidade
Algumas abordagens
- Permitir todos os tipos de coerção
- Não permitir coerção
- Só permitir coerção por alargamento (caso de Java)
Sobrecarga: operador ou identificador com usos distintos
Somente deve ser aceito se não houver ambiguidades
Exemplo
- Operador - e + em C (e em várias linguagens)
main() { int a = 1, b = 2; float x = 1.2, y = 2.4; x = a + b; x = x + y; }
Sobrecarga nos faz pensar em operações polimórficas
Mas na realidade, não
main() {
int a = 1, b = 2;
float x = 1.2, y = 2.4;
x = a + b;
x = x + y;
}
Veja ./sobrecarga.c
- Compile com
gcc -S sobrecarga.c
, olhe o arquivosobrecarga.s
C, Modula-2 tem sobrecarga embutida Java
- Sobrecarga de métodos
C++, Ada
- Sobrecarga de métodos
- Sobrecarga de operadores com algumas regras
- Ordens de precedência e associatividade são mantidas
- Não pode-se sobrecarregar
::
.
sizeof
Sobrecarregando os operadores + e * para complexos
class Complex {
double re, im;
public:
//...
Complex operator+ (Complex);
Complex operator* (Complex);
Exemplo de Uso
Complex d = a + b * c;
Uso do operador é apenas um atalho Exemplo
void f(Complex a, Complex b) {
Complex c = a + b;
Complex d = a.operator+(b);
}
Dependente do contexto – distinção pelo valor de retorno
- Abordagem não utilizada
- Exemplos
void foo (void); int foo (void);
Independente do contexto – distinção pelos parâmetros
- Mais comum, tipo de retorno é ignorado
- Exemplos
void foo (void) { } void foo (float a) { } void foo (int x, int y) { } main(){ foo(); foo(4.2); foo(3, 1); }
Quais funções são chamadas?
Quais erros seriam detectados?
- Case Dependente versus Caso Independente do contexto
\normalsize
void f(void) { } void f(float) { } void f(int, int) { } void f(float, float) { } int f(void) { } main(){ f(); f(2.3); f(4, 5); f(2.2f, 7.3f); f(3, 5.1f); f(1l, 2l); }