2011-03-28 34 views
6

Acabo de empezar a aprender Scala. Me siento bastante cómodo con el diseño de OO, y menos con la programación funcional; aunque, he estado programando lo suficiente para que FP no sea completamente antinatural tampoco para mí. Desde el primer día de mi aventura en Scala, tuve esta, digamos, inquietud con la aparente dialéctica que está ocurriendo entre OO y FP. Claramente, uno puede recorrer todo el camino de una forma u otra. Mi primera tendencia fue ver las clases como una especie de paquetes que mantienen juntas las funciones que quiero pasar, que equilibra las escalas hacia el lado funcional. Siento que tiene que haber una mejor forma de equilibrar el acto. Tampoco estoy seguro de cómo proceder con ciertas situaciones familiares en este escenario. Por ejemplo, si tuviera la (artificial) de clase siguiente:Función Scala vs clase Dicotomía

class ValueGenerator { 
    def value() = { 
     "1" 
    } 
    def value(line: String) = { 
     line 
    } 
} 

en la programación OO yo llamaría el value con la firma apropiada cuando lo necesitaba, para obtener el resultado que necesito. Los métodos tienen la misma firma, porque lógicamente corresponden a acciones similares. En OO, me gustaría pasar alrededor de la referencia del objeto, y los métodos que reciben un objeto ValueGenerator haría la llamada a la derecha value dependiendo de la situación. Por lo que puedo ver, al menos es mi tendencia, que en Scala la norma es pasar el método. Pero en este caso, aunque los métodos hacen lo mismo, no tienen la misma firma, por lo tanto no pueden sustituirse entre sí (¿o sí?). En otras palabras, ¿puede el método emisor decidir la función que se enviará independientemente de la firma de la función? Esto parece poco probable ya que el receptor no sabría cómo invocarlo. ¿Cuál es la acción correcta en una situación como esta? ¿O uno va con su instinto? ¿Hay una regla general que sigas cuando se trata de OO vs FB?

Como nota al margen, fue interesante ver que un amigo mío que también está aprendiendo a Scala tenía los mismos pensamientos (o falta de ellos) que yo sobre este tema.

+2

Los métodos no tienen la misma firma: uno toma un argumento de tipo Cadena, el otro no tiene argumentos. De la sección 2.10.2 de la Especificación JVM: "La firma de un método consiste en el nombre del método y el número y tipo de parámetros formales (§2.10.1) del método [...]" –

+0

Además, usted debería notar que un método es algo, una función es otra cosa. No pasa métodos, solo puede pasar funciones. Sin embargo, puede elevar un método a una función. –

+0

Véase también http://jim-mcbeath.blogspot.com/2009/05/scala-functions-vs-methods.html –

Respuesta

4

En el código que ha proporcionado, no hay ninguna razón es necesario tener dos firmas de métodos distintos: la sesión

class ValueGenerator { 
    def value(line: String = "1") = { 
    line 
    } 
} 

REPL:

scala> new ValueGenerator() 
res1: ValueGenerator = [email protected] 

scala> res1.value("Foo") 
res2: String = Foo 

scala> res1.value() 
res3: String = 1 

Tenga en cuenta que sólo se puede hacer esto con métodos. Las funciones no apoyar los argumentos por defecto:

scala> val f = res1.value(_) 
f: (String) => String = <function1> 

scala> f("Bar") 
res5: String = Bar 

scala> f() 
***Oops*** 

scala> val f = (line: String) => line  
f: (String) => String = <function1> 

scala> val f = (line: String = "1") => line 
***Oops*** 
9

no tienen la misma firma, y ​​por lo general se desee métodos que no tienen la misma firma para tener diferentes nombres. La sobrecarga le compra muy poco y le cuesta mucho (es decir, inferencia de tipo y resolución implícita).

Dicho esto, no se pueden sustituir porque no tienen el mismo tipo. Si convierte estos métodos en funciones, uno tendría el tipo Function0[String] y el otro tendría el tipo Function1[String, String].

2

Por lo que puedo ver, al menos es mi tendencia, que en Scala la norma es pasar el método.

Dudo que esa sea la norma (¿por qué crees?) O que incluso hay una norma para esto en Scala.

Pero en este caso, aunque los métodos hacen lo mismo, no tienen la misma firma, por lo tanto no se pueden sustituir entre sí (¿o sí?). En otras palabras, ¿puede el método emisor decidir la función que se enviará independientemente de la firma de la función?

No se pueden sustituir entre sí porque tienen diferentes firmas, por lo que tienen diferentes tipos.

El escenario que describe suena como un ajuste perfecto para la forma OO de hacer las cosas: simplemente pase el objeto ValueGenerator y deje que el cliente decida qué método llamar en ese objeto.

+0

Bueno, no sé cuál es la norma, pero hay patrones de diseño y mejores prácticas para cualquier idioma dado, y dado el tiempo, todos los idiomas tienden a converger libremente en dicho uso. Por ejemplo, en este caso, podría hacerlo de la manera OO, pero también podría almacenar 'line' en la clase, y solo tengo un método para' value', que puedo pasar, para manejarlo. Dos enfoques diferentes para lograr lo mismo. – delmet