2009-12-09 13 views
5

¿Existe alguna forma recomendada de modelar múltiples niveles de herencia en F #, presumiblemente utilizando una unión discriminada?Modelado de niveles múltiples de herencia mediante uniones discriminadas

Tomando algo como lo siguiente en C#:

class Expr { } 
class SourceExpr : Expr { } 
class JoinExpr : SourceExpr { } 
class TableExpr : SourceExpr { } 

que he hecho esto en C#:

type SourceExpr = 
    | Join of JoinExpr 
    | Table of TableExpr 

type Expr = 
    | Source of SourceExpr 
    | ... 

¿Hay una mejor manera? ¿Esto proporciona el mismo comportamiento polimórfico que la herencia?

Respuesta

8

Es difícil ser demasiado preceptivo aquí sin más información. Dependiendo de lo que intente hacer, puede tener más sentido usar una jerarquía de clases o una unión discriminada (UD). Las compensaciones más comunes/inocentes son que las jerarquías de clase son 'abiertas' mientras que las DU están 'cerradas'. Es decir, puede agregar fácilmente nuevos tipos a una jerarquía de clases, pero agregar una nueva operación (método abstracto en la clase base) requiere cambiar todas las clases existentes. Por el contrario, con los DU puede agregar fácilmente una nueva operación (función que coincide con el tipo de datos), pero para agregar un nuevo caso (subclase) debe redefinir el tipo y actualizar todas las operaciones existentes para tratar el nuevo caso . (Esto a veces se denomina "problema de expresión").

Un ejemplo típico que es bueno para los DU es un compilador; tiene un árbol de sintaxis abstracta de lenguaje donde el lenguaje y la estructura de árbol son fijos, pero puede crear muchas operaciones diferentes de transformación de árbol dentro del compilador. Un ejemplo típico que es bueno para las jerarquías de clase son los marcos de IU; tiene algunas clases base que definen todas las operaciones que los widgets deben suministrar (Draw, Resize, ...) pero luego los usuarios agregarán sus propios subtipos personalizados con capacidades adicionales.

+0

Estoy trabajando en un analizador sintáctico, por lo que creo que los DU son la elección correcta. Pero hay expresiones que parecen heredar de otros. Hay funciones que deberían aceptar una combinación o tabla, que son ambas fuentes. También hay funciones que deberían aceptar un Expr, de los cuales Source es una de las muchas opciones. No puedo dejar de pensar en términos de OO, pero me pregunto si existe una mejor manera de modelar esta jerarquía relativamente estática mientras se mantiene el mismo tipo de comportamiento polimórfico. – Daniel

+0

Modelarlo con tipos funcionará bien. Si tiene dos tipos que son "también" lo mismo, agregue un nuevo tipo que discrimine entre ellos y use eso. El único inconveniente es que tendrás que hacer más deconstrucción, pero la coincidencia de patrones y los patrones activos donde los necesites lo hacen bastante tolerable. Estoy haciendo esto con algunos tipos recursivos bastante complicados y un analizador FParsec y funciona bastante bien. –

0

puede modelar las clases usando herencia en F # tal como lo hace en C# .... O ... puede modelar los requisitos usando uniones discriminadas como muestra.

No, las uniones discriminadas no permiten el mismo tipo de comportamiento polimórfico, en particular, es posible que tenga que modificar todas las coincidencias de patrones si agrega nuevos casos.

Tiene sus ventajas, aunque tiendo a escribir código con uniones discriminadas en F # y herencia en C# ... A MENOS QUE ... Tengo una preocupación específica acerca de la extensibilidad.

no está modelando ningún nivel de herencia usando uniones no discriminadas ... está comparando manzanas con zanahorias.

puede modelar los mismos requisitos en ambos paradigmas ... Iría a una unión discriminada en su contexto ... Creo que hará que el código sea más simple de leer ... pero eso es subjetivo.

Cuestiones relacionadas