2012-01-20 26 views
17

¿El motivo F # no admite clases anidadas técnicas, estilísticas, arbitrarias?¿Por qué F # no admite clases anidadas?

Al echar un vistazo al BCL en Reflector, las clases anidadas se usan para los enumeradores, DynamicMetaObject s, y probablemente algunas otras cosas más.

Eso despertó mi curiosidad sobre F # que no tiene esta función. Soy consciente de que hay otras formas de hacer lo mismo. Soy mayormente curioso.

+6

Admite clases anidadas (estáticas): 'módulo X = módulo Y = let j = 3 ;;' –

Respuesta

19

Supongo que las clases anidadas no eran una característica central del modelo de objetos .NET y simplemente se soltaron para guardar los recursos. Puede haber algunas dificultades técnicas (es decir, con visibilidad o con definiciones de tipo recursivo), pero no creo que eso sea un problema importante.

Durante muchos casos en los que se utilizarían clases anidadas en C#, como iteradores, puede muy bien utilizar expresiones de objetos, por lo que supongo que son de alguna sustitución de formas para las clases anidadas:

type Collection() = 
    member x.GetEnumerator() = 
    let n = ref 0 
    { new IEnumerator with 
     member x.Current = box n.Value 
     member x.MoveNext() = incr n; true 
     member x.Reset() = n := 0 } 

Aunque se trata de bastante similar a las clases anidadas, no se compila como clase anidada y el cuerpo de una expresión de objeto no puede acceder a los miembros privados de Collection. Supongo que esto podría complicar un poco la compilación de expresiones, porque las expresiones de objetos pueden aparecer fuera del contexto de una clase ...

En realidad, es posible acceder a private miembros desde la expresión del objeto, aunque el código todavía no está compilado como una clase anidada. Ver comentarios para más detalles.

+1

Una pequeña corrección: es posible hacer referencia a 'let' bindings/private members del tipo adjunto de una expresión de objeto. Esto, en mi opinión, los convierte en una mejor solución que las clases anidadas. – Daniel

+1

@Daniel Tienes razón: puedes acceder a miembros privados (tuve un error en mi prueba). Curiosamente, cuando haces eso, el miembro al que estás accediendo está en línea o compilado como 'interno' para hacer que este acceso sea seguro (pero el compilador de F # lo trata como' privado '). –

+3

@Tomas: en realidad, de acuerdo con la especificación F #, "La forma compilada por el CLI de _todas las entidades no públicas es interna". ... por lo que uno no debería otorgar privilegios [] a los clientes que no sean F # ... ¡verán todo lo que es _private_ en el ensamblado F # como _internal_! –

2

F # se basa principalmente en Caml, que no tiene clases anidadas.

Probablemente no fue agregado simplemente porque no es de alta prioridad. Dado que puede declarar tipos de datos que no son visibles fuera de un módulo, permitir clases internas no supondría una gran diferencia en lo bien encapsulado que puede ser su código.

+10

Probablemente no sea el caso, aunque F # se basa principalmente en OCaml, el modelo de objetos utilizado en F # es mucho más basado en .NET que en OCaml. –

+0

+1 por mencionar que no son necesarios porque puede usar archivos de firma para ocultarlos. – YellPika

Cuestiones relacionadas