简体   繁体   中英

f# private class inside public one

I have a Java class and I need to write a similar one in F#. How can I define a private class inside public in f#?

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

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

It is perfectly possible in F#. F# is functional first, not pure functional - and this is one of its major strengths. F# is pragmatic and this construct below lets one achieve exactly the same result, even though the KnownParsing type is not "nested" in Java or C# sense.

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 are useful for implementing interfaces or abstract classes, but the "parent" class (the one that creates an object expression) won't be able to access its internals. Or, more correctly, there is no way to create internals other than interface/abstract members in any way other than via ref cells outside the object expression itself. This has performance implications such as GC pressure for ref cells.

See this example in my open-source project about how object expressions and "nested via and" types work interchangeably for IEnumerator implementation. On this line I use private type as in this answer and it works well. In the whole project I use F# in mostly imperative way because this is the only way to get decent performance. And I must say I like F# most often over C# even for imperative code.

As people have said, F# does not currently support nested classes.

One workaround is as shown by VB, with two separate classes, one of which is private.

However, if the inner class is simple (with one or two methods only) then there is an alternative approach, which is to use a closure as a poor-person's object .

In the code below, the KnownParsing function creates two functions and returns them as a pair. The knownParsingSet then contains pairs of functions, rather than instances of classes.

If there is only one method in the nested class, then this approach is fine because a one method class is basically just a function. For more than one method in the nested class, it gets quite ugly, which is why F# people solve the problem using other techniques instead. :)

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())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM