2016-01-25 11 views
5

Ho una classe Java e ho bisogno di scrivere una simile in F #. Come posso definire una classe privata in pubblico in f #?f # classe privata all'interno di uno pubblico

public class KnownRuleGoals { 
    void record() { 
     knownParsingSet.add(new KnownParsing()); 
    } 

    private class KnownParsing { 
     Rule [] knownParsing; 
     KnownParsing() { 
     ... 
     } 
     void doWork() { ... } 
    } 
} 
+1

[F # non supporta classe nidificazione] (http://stackoverflow.com/questions/8948332/why-doesnt-f-support-nested-classes). – vcsjones

+2

Nella programmazione funzionale si pensa innanzitutto alle funzioni, in OO si pensa prima agli oggetti. Stai pensando oggetto quando dovresti pensare a una funzione. Pensa come posso creare un record di funzione pubblica() che abbia una funzione nascosta KnownParsing(). Una funzione all'interno di un'altra funzione è essenzialmente privata. –

+3

Perché tutti i voti negativi? Sembra una domanda ragionevole. – Mathias

risposta

7

È perfettamente possibile in F #. F # è funzionale in primo luogo, non pura funzionalità - e questo è uno dei suoi principali punti di forza. F # è pragmatico e questo costrutto sotto consente di ottenere esattamente lo stesso risultato, anche se il tipo KnownParsing non è "annidato" in senso Java o C#.

type KnownRuleGoals() = 
    let knownParsingSet : List<KnownParsing> = List() 
    member this.Record() = 
     knownParsingSet.Add(new KnownParsing()) 

and private KnownParsing() = 
    let foo = "private fields" 
    member this.DoWork() = failwith "TODO implementation" 

Object expressions sono utili per interfacce o classi astratte attuazione, ma la classe "padre" (quello che crea un'espressione oggetto) non sarà in grado di accedere alle parti interne. O, più correttamente, non c'è modo di creare interni diversi dai membri di interfaccia/astratti in nessun modo se non attraverso le celle di rif. Al di fuori dell'espressione dell'oggetto stesso. Questo ha implicazioni sulle prestazioni come la pressione GC per le celle ref.

Vedere l'esempio this nel mio progetto open source su come le espressioni oggetto ei tipi "nested via e" funzionano in modo intercambiabile per l'implementazione IEnumerator. Su this line Io uso il tipo private come in questa risposta e funziona bene. Nell'intero progetto uso F # in modo prevalentemente imperativo perché questo è l'unico modo per ottenere prestazioni decenti. E devo dire che mi piace F # più spesso su C# anche per codice imperativo.

+0

Grazie mille per la risposta! –

5

Come si è detto, F # non supporta attualmente classi annidate.

Una soluzione è come mostrato in V.B., con due classi separate, una delle quali è privata.

Tuttavia, se la classe interna è semplice (solo con uno o due metodi), esiste un approccio alternativo, che utilizza una chiusura come poor-person's object.

Nel codice seguente, la funzione KnownParsing crea due funzioni e le restituisce in coppia. Il numero knownParsingSet contiene quindi coppie di funzioni, anziché istanze di classi.

Se esiste un solo metodo nella classe nidificata, questo approccio va bene perché una classe di un metodo è fondamentalmente solo una funzione. Per più di un metodo nella classe annidata, diventa piuttosto brutto, motivo per cui le persone F # risolvono il problema con utilizzando invece altre tecniche. :)

type KnownRuleGoals() = 

    let knownParsingSet = System.Collections.Generic.HashSet() 

    // use a function 
    let KnownParsing() = 
     let knownParsing = [||] 
     let doWork() = 
      () // do something 
     let doWork2() = 
      () // do something 
     // return the pair of functions 
     doWork,doWork2 

    // the member/method comes after the closure because 
    // definitions must come before usage. 
    member this.record() = 
     knownParsingSet.Add(KnownParsing()) 
+0

Assegnazioni aggiuntive solo per essere pura - tupla + 2 Funcs almeno, senza speranza di inlining di Jit. Fammi solo capire perché così tanti utenti di F # sono così contrari a soluzioni molto più semplici a favore del purismo? Questa domanda mi perseguita da più di 2 anni. –

+0

La domanda non riguardava le prestazioni, solo su come implementare le classi annidate. Certamente non direi che questa è una soluzione ottimale! Stavo solo mostrando una soluzione alternativa per l'OP. – Grundoon

+0

@ V.B. Per me è che il codice funzionale è più probabile che sia corretto quando è puramente funzioni. Se altri linguaggi funzionali puri come [ML] (https://en.wikipedia.org/wiki/ML_ (programming_language)) diventassero più stream principali e avessero strumenti e supporto migliori, li userei invece. Se [Coq] (https://coq.inria.fr/) potrebbe essere usato come linguaggio di programmazione, lo userei. Se [Mercury] (https://mercurylang.org/) fosse più mainstream e avessi strumenti migliori, lo userei. Mi affido anche a [Algebraic Data Types] (https://en.wikipedia.org/wiki/Algebraic_data_type) e quindi disprezzo se affermazioni –

Problemi correlati