2009-02-18 14 views
13

Si agrego una nueva clase de caso, ¿eso significa que necesito buscar a través de todo el código de coincidencia de patrón y averiguar dónde se debe manejar la nueva clase? He estado aprendiendo el idioma recientemente, y cuando leí sobre algunos de los argumentos a favor y en contra de la coincidencia de patrones, he estado confundido acerca de dónde debería usarse. Véase el siguiente:¿La coincidencia de patrones de Scala viola el principio abierto/cerrado?

Pro: Odersky1 y Odersky2

contra: Beust

Los comentarios son bastante buenos en cada caso, también. Entonces, ¿el patrón coincide con algo para entusiasmar o algo que debería evitar usar? En realidad, me imagino que la respuesta es "depende de cuándo la usas", pero ¿cuáles son algunos casos de uso positivo y cuáles son algunos negativos?

+0

El enlace de Beust está roto, aparentemente se debe a un cambio de esquema de URL. Traté de ver si podía averiguar cuál era la publicación, pero no estoy seguro. Proporcione un enlace corregido o más información para continuar (¿cuál era el título de la publicación?). –

Respuesta

22

Jeff, creo que tienes la intuición correcta: depende.

Las jerarquías de clases orientadas a objetos con envío de métodos virtuales son buenas cuando tiene un conjunto relativamente fijo de métodos que deben implementarse, pero muchas subclases potenciales que pueden heredar de la raíz de la jerarquía e implementar esos métodos. En dicha configuración, es relativamente fácil agregar nuevas subclases (solo implementar todos los métodos), pero es relativamente difícil agregar nuevos métodos (debe modificar todas las subclases para asegurarse de que implementen correctamente el nuevo método).

Los tipos de datos con funcionalidad basada en la coincidencia de patrones son buenos cuando tiene un conjunto relativamente fijo de clases que pertenecen a un tipo de datos, pero muchas funciones potenciales que operan en ese tipo de datos. En dicha configuración, es relativamente fácil agregar nuevas funcionalidades para un tipo de datos (solo coincidencia de patrones en todas sus clases), pero es relativamente difícil agregar nuevas clases que sean parte del tipo de datos (debe modificar todas las funciones que coinciden) en el tipo de datos para asegurarse de que sean compatibles con la nueva clase).

El ejemplo canónico para el enfoque OO es la programación de GUI. Los elementos de GUI deben admitir muy poca funcionalidad (dibujarse en la pantalla es el mínimo indispensable), pero se agregan nuevos elementos de GUI todo el tiempo (botones, tablas, gráficos, controles deslizantes, etc.). El ejemplo canónico para el enfoque de coincidencia de patrones es un compilador. Los lenguajes de programación generalmente tienen una sintaxis relativamente fija, por lo que los elementos del árbol de sintaxis cambian raramente (si es que lo hacen), pero se agregan constantemente nuevas operaciones en árboles de sintaxis (optimizaciones más rápidas, análisis de tipo más exhaustivos, etc.).

Afortunadamente, Scala le permite combinar ambos enfoques. Las clases de casos pueden combinarse con patrones y admitir el envío de métodos virtuales. Las clases regulares admiten el envío de métodos virtuales y se pueden combinar con el patrón definiendo un extractor en el objeto complementario correspondiente. Depende del programador decidir cuándo cada enfoque es apropiado, pero creo que ambos son útiles.

16

Si bien respeto a Cedric, está completamente equivocado sobre este tema. La coincidencia de patrones de Scala se puede encapsular por completo a partir de los cambios de clase cuando se desee. Si bien es cierto que un cambio a una clase de caso requeriría cambiar cualquier instancia de coincidencia de patrón correspondiente, esto es solo cuando se usan tales clases de manera ingenua.

El patrón de Scala que coincide con siempre delega al deconstructor del objeto complementario de una clase. Con una clase de caso, este deconstructor se genera automáticamente (junto con un método de fábrica en el objeto complementario), aunque aún es posible anular esta versión generada automáticamente. En todo momento, puede ejercer un control total sobre el proceso de coincidencia de patrones, aislando cualquier patrón de posibles cambios en la clase misma. Por lo tanto, la coincidencia de patrones es simplemente otra forma de acceder a los datos de clase a través del filtro seguro de encapsulación, como cualquier otro método.

Por lo tanto, la opinión del Dr. Odersky sería la de confiar aquí, particularmente dado el enorme volumen de investigación que ha realizado en el área de programación y diseño orientado a objetos.

En cuanto a dónde se debe utilizar, eso es completamente según el gusto. Si hace que su código sea más conciso y fácil de mantener, úselo. De lo contrario, no. Para la mayoría de los programas orientados a objetos, la coincidencia de patrones es innecesaria. Sin embargo, una vez que comience a integrar expresiones más funcionales (Option, List, etc.) creo que encontrará que la coincidencia de patrones reducirá significativamente los gastos indirectos sintácticos y mejorará la seguridad ofrecida por el sistema de tipos. En general, cada vez que desee extraer datos mientras prueba simultáneamente alguna condición (por ejemplo, extraer un valor de Some), es probable que la coincidencia de patrones sea útil.

1

La coincidencia de patrones es definitivamente buena si está realizando una programación funcional. En el caso de OO, hay algunos casos en los que es bueno. En el ejemplo de Cedric en sí mismo, depende de cómo ve conceptualmente el método print(). ¿Es un comportamiento de cada objeto Term? ¿O es algo fuera de eso? Yo diría que está afuera, y tiene sentido hacer una coincidencia de patrones. Por otro lado, si tiene una clase Employee con varias subclases, es una opción de diseño deficiente hacer la coincidencia de patrones en un atributo (por ejemplo, nombre) en la clase base.

También la coincidencia de patrones ofrece una forma elegante de desempaquetar miembros de una clase.

Cuestiones relacionadas