2016-01-25 7 views
5

Ich habe eine Java-Klasse und ich muss eine ähnliche in F # schreiben. Wie kann ich eine private Klasse innerhalb von public in f # definieren?f # private Klasse innerhalb der öffentlichen

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

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

[F # unterstützt Klasse Verschachtelung nicht] (http://stackoverflow.com/questions/8948332/why-doesnt-f-support-nested-classes). – vcsjones

+2

In der funktionalen Programmierung denkt man zuerst an Funktionen, in OO denkt man zuerst an Objekte. Sie denken Objekt, wenn Sie denken sollten, Funktion. Denken Sie daran, wie ich einen öffentlichen Funktionsdatensatz() erstellen kann, der eine versteckte Funktion KnownParsing() hat. Eine Funktion innerhalb einer anderen Funktion ist im Wesentlichen privat. –

+3

Warum alle Downstimmen? Das klingt nach einer vernünftigen Frage. – Mathias

Antwort

7

Es ist in F # durchaus möglich. F # ist zuerst funktional, nicht rein funktional - und das ist eine seiner großen Stärken. F # ist pragmatisch und dieses Konstrukt unten ermöglicht es, genau das gleiche Ergebnis zu erzielen, auch wenn der Typ KnownParsing nicht in Java oder C# -Sequenzen "verschachtelt" ist.

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 sind nützlich für die Schnittstellen oder abstrakte Klassen Umsetzung, aber die „Eltern“ Klasse (die, die ein Objekt Ausdruck schafft) nicht in der Lage sein, den Zugriff auf seine Einbauten. Oder, genauer gesagt, es gibt keine Möglichkeit, andere Einbauten als Interface/Abstract-Member auf andere Weise als über Ref-Zellen außerhalb des Objektausdrucks selbst zu erstellen. Dies hat Auswirkungen auf die Leistung, wie GC-Druck für Ref-Zellen.

Siehe this Beispiel in meinem Open-Source-Projekt darüber, wie Objektausdrücke und "geschachtelt über und" Typen austauschbar für IEnumerator Implementierung funktionieren. Auf this line verwende ich private Typ wie in dieser Antwort und es funktioniert gut. Im ganzen Projekt verwende ich F # in meist imperativer Weise, da dies der einzige Weg ist, anständige Leistung zu bekommen. Und ich muss sagen, ich mag F # am häufigsten über C#, auch für Imperativ-Code.

+0

Vielen Dank für die Antwort! –

5

Wie bereits erwähnt, unterstützt F # derzeit keine verschachtelten Klassen.

Eine Abhilfe ist, wie von V. B. gezeigt, mit zwei separaten Klassen, von denen eine privat ist. Wenn die innere Klasse einfach ist (nur mit einer oder zwei Methoden), gibt es einen alternativen Ansatz, , der einen Abschluss als poor-person's object verwenden soll. Im folgenden Code erstellt die Funktion KnownParsing zwei Funktionen und gibt sie als Paar zurück. Die knownParsingSet enthält dann Paare von Funktionen anstelle von Instanzen von Klassen.

Wenn es nur eine Methode in der geschachtelten Klasse gibt, dann ist dieser Ansatz in Ordnung, da eine Methode nur eine Funktion ist. Für mehr als eine Methode in der geschachtelten Klasse wird es ziemlich hässlich, weshalb F # Leute das Problem mit anderen Techniken lösen. :)

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

Zusätzliche Zuweisungen nur um rein zu sein - Tupel + 2 Funcs zumindest, ohne Hoffnung auf Inlining durch Jit. Lasst mich einfach verstehen, warum so viele F # -Benutzer sich gegen viel einfachere Lösungen zugunsten von Purismus aussprechen? Diese Frage verfolgt mich seit 2 Jahren. –

+0

Die Frage war nicht die Leistung, sondern nur die Implementierung geschachtelter Klassen. Ich würde sicherlich nicht behaupten, dass dies eine optimale Lösung ist! Ich habe gerade eine alternative Lösung für das OP gezeigt. – Grundoon

+0

@ V.B. Für mich ist es eher so, dass funktionaler Code korrekt ist, wenn er rein funktioniert. Wenn andere reine funktionale Sprachen wie [ML] (https://en.wikipedia.org/wiki/ML_ (programming_language)) mehr Mainstream werden würden und bessere Werkzeuge und Unterstützung hätten, würde ich sie stattdessen verwenden. Wenn [Coq] (https://coq.inria.fr/) als Programmiersprache verwendet werden könnte, würde ich das verwenden. Wenn [Mercury] (https://mercylylang.org/) mehr Mainstream wäre und bessere Werkzeuge hätte, würde ich das verwenden. Ich verlasse mich auch auf [Algebraic Datentypen] (https://en.wikipedia.org/wiki/Algebraic_data_type) und verachte so, wenn Aussagen –

Verwandte Themen