2009-10-20 14 views
9

c, Java y muchos otros idiomas no prestan atención a los valores de devolución.¿Por qué los idiomas no permiten la sobrecarga de métodos por valor de retorno?

int i = func() 
float f = func() 
int func() { return 5 } 
float func() { return 1.3} 

¿Por qué no es legal lo anterior? ¿Es más difícil programar

int i = func(func(func(func2(func3())))) //you dont know what you are getting 

¿Es difícil escribir un compilador? ¿hay más lenguaje sin ambigüedad? ¿Hay algún lenguaje que pueda hacer lo anterior?

+0

¿Has probado LISP? Si no lo intentas, podría solucionar tu problema. – Zinx

+0

posible duplicado de [Función de sobrecarga por tipo de devolución?] (Http://stackoverflow.com/questions/442026/function-overloading-by-return-type) – nawfal

Respuesta

14

Digamos que se permitió que uno lo haría esta llamada:

func(); 

que tal vez no el la respuesta completa, pero creo que es una de las razones por las que no es legal.

+1

ese es un buen punto. Los parámetros son generalmente necesarios para las funciones, pero el manejo del valor de retorno no lo es. – Herms

+2

Creo que es una mala práctica no manejar los valores devueltos. Esto debe ser nulo arrojando una excepción o el valor de retorno debe ser verificado. Sin embargo var v = func(); (Asignación de estilo C#) puede causar problemas ... (hmmmm)) –

+0

+1 por hacerme admitir la var v = arriba –

17

¿Qué pasa con este caso?

class A implements Foo { /*...*/ } 
class B implements Foo { /*...*/ } 

A func() { return new A(); } 
B func() { return new B(); } 

Foo v = func(); // which do you call?! 

Ya existen problemas con la ambigüedad cuando se permite la sobrecarga de un solo nombre de función que toma diferentes argumentos. Tener que verificar también el tipo de retorno probablemente haría que resolver la función correcta sea mucho más difícil.

Estoy seguro de que un lenguaje podría implementar eso, pero haría las cosas mucho más complicadas, y generalmente haría el código más difícil de entender.

+2

De manera similar, ¿qué debería hacer 'System.out.println (func () + func()) salida? – notnoop

+0

Eso haría que el código sea más difícil de entender. +1. Tal vez marque esto como correcto (quiero ver otras respuestas) –

+0

¿Qué tal si se requiere que una de las sobrecargas se marque como "preferida", mientras que otras solo se usan cuando el tipo de devolución se lanzará inmediatamente o se forzará a otro tipo? (para lo cual se proporciona una sobrecarga más precisa), o cuando se ignora el tipo de devolución (en cuyo caso se usaría una sobrecarga 'void' si se suministra). – supercat

6

Por ejemplo, un C++, tenga en cuenta:

void g(int x); 
void g(float x); 
g(func()); 

¿Cuál de las funciones sobrecargadas g() se llamaría?

+1

en este caso podría hacer lo que C++ hace a veces y compila con un error ambiguo forzando al usuario a escribir 'g ((Float_OR_int_type) func());' –

+0

Incluso eso no ayudaría. ¿Qué sucede si tiene múltiples métodos que devuelven un tipo que puede ser lanzado válidamente al objeto al que está enviando? int se puede convertir para flotar, y viceversa. – Herms

1

La mayoría de los idiomas permiten operaciones de modo mixto con coerción automática (por ejemplo, float + int), donde las interpretaciones múltiples son legales. Sin coerción, trabajar con múltiples tipos numéricos (corto, int, largo, flotante, doble) se volvería muy engorroso; con la coacción, la desambiguación basada en el tipo de retorno llevaría a un código difícil de entender.

1

Permitir esto puede presentar problemas. Por ejemplo:

int i = func2(func()); 
int func() { return 5; } 
float func() { return 1.3; } 
int func2(float a) { return a; } 
int func2(int a) { return a; } 

Esta es ambigua.

+0

¿Cuál sería el error al especificar que cada firma de método debe tener una implementación que está marcada como preferida, excepto cuando el resultado de la función se asignó a una variable o inmediatamente se encasiló? – supercat

3

Perl permite un cierto grado de variación del tipo de retorno, ya que las funciones pueden indicar en qué tipo de contexto están siendo evaluadas. Por ejemplo, una función que puede devolver una matriz puede ver que se está ejecutando en un contexto escalar. y simplemente devuelve la longitud putativa directamente, ahorrando la asignación e inicialización de la matriz solo para obtener su longitud.

+0

Lo que funciona para Perl, pero hay varias cosas en Perl que no creo que funcionen en un lenguaje más convencional. Sin mencionar que Perl no tiene un sistema de tipos en el sentido normal: los tipos son $ escalares, @arrays, #hashes, @typeglobs, y me parece que olvidé uno. No hay distinción entre entero, flotante y cadena, y los operadores tienen que decidir si actuar numéricamente ($ i + 1) o con cadenas ($ i + "1"). –

+0

@David: No creo que estuviera elogiando las virtudes de Perl en mi respuesta, ni sugiriendo que tales cosas * deberían * agregarse a otros idiomas. Simplemente estaba respondiendo la parte de la pregunta que pregunta qué hay allí afuera. – Novelocrat

10

Sí, permitir la sobrecarga en los tipos de devolución complica un idioma. Esto complica la resolución de identificadores sobrecargados (por ejemplo, nombres de funciones). Pero no es imposible, p. Haskell permite sobrecargar la función según su tipo de devolución.

class Num a where 
    fromInteger :: Integer -> a 
    ... 

Num es una clase de tipos en Haskell con un método llamado fromInteger que es una función de un tamaño arbitrario Integer a un tipo arbitrario, que tiene una instancia de Num. El mecanismo de clase de tipo Haskell es bastante diferente del concepto de clase de lenguajes orientados a objetos. Por lo tanto, mi explicación puede sonar extraña.

Pero, el resultado es que puedo usar la función fromInteger y, dependiendo del contexto de la llamada, se ejecutan diferentes implementaciones en tiempo de compilación.

Existe toda una línea de investigación sobre sistemas tipo, que hizo posible esta función. Por lo tanto, diría que es factible en lenguajes tipados estáticamente. Los lenguajes con tipado dinámico requerirían viajes en el tiempo o algunas ideas inteligentes.

9

Para evitar ambigüedades.

a(int) 
a(bool) 
int b() 
bool b() 

a(b()) -- Which b? 

Aquí, la inferencia tiene una dependencia cíclica. Cuál b depende de qué a, pero a depende de qué b, por lo que se atasca.

No permitir la sobrecarga de los tipos de retorno garantiza que la inferencia de tipo sea acíclica. El tipo de retorno siempre puede ser determinado por los tipos de parámetros, pero los tipos de parámetros no pueden ser determinados por el tipo de retorno, ya que a su vez pueden ser determinados por los tipos de parámetros que está tratando de encontrar.

+1

+1 para un ejemplo muy agradable, conciso y directo. –

+1

+1 para mencionar la inferencia de tipo –

+0

Hay muchas situaciones ambiguas, pero eso no implicaría que la sobrecarga no podría ser útil si (1) se utilizara alguna función "primaria" excepto en los casos en que otra era claramente superior, y (2) en casos que aún serían ambiguos, un compilador podría usar cualquiera de ellos. Considere las funciones (int32, int32) -> int32, (int32, int32) -> int64, y (int64, int64) -> int64. Si producen un comportamiento semánticamente idéntico en los casos en que el valor calculado sería dentro de un int32, un compilador podría usar (int64, int64) -> int64 siempre, pero el rendimiento podría ser mejor si se usara (int32, int32) -> int32 en su lugar. – supercat

Cuestiones relacionadas