Вопрос: f # частный класс внутри публичного


У меня есть класс Java, и мне нужно написать подобный в F #. Как определить частный класс внутри public в f #?

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

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

5


источник


Ответы:


Это вполне возможно в F #. F # является функциональным первым, а не чисто функциональным - и это одна из его основных сильных сторон. F # является прагматичным, и эта конструкция ниже позволяет достичь точно такого же результата, хотя KnownParsing тип не «вложен» в Java или 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"

Выражения объектов  полезны для реализации интерфейсов или абстрактных классов, но «родительский» класс (тот, который создает выражение объекта) не сможет получить доступ к его внутренним элементам. Или, вернее, нет возможности создавать внутренние элементы, отличные от интерфейсных / абстрактных, каким-либо образом, кроме как через ячейки ref вне самого выражения объекта. Это имеет такие последствия, как давление газа для рефлексивных клеток.

Видеть это  пример в моем проекте с открытым исходным кодом о том, как объектные выражения и «вложенные через» и «типы» работают взаимозаменяемо для IEnumerator реализация. На эта линия  я использую private типа, как в этом ответе, и он работает хорошо. Во всем проекте я использую F # в основном императивным способом, потому что это единственный способ получить достойную производительность. И я должен сказать, что мне нравится F # чаще всего над C # даже для императивного кода.


7



Как говорили люди, F # в настоящее время не поддерживает вложенные классы.

Один способ обхода такой, как показано В.Б., с двумя отдельными классами, один из которых является частным.

Однако, если внутренний класс прост (только с одним или двумя методами), то существует альтернативный подход, который должен использовать замыкание как объект бедного человека ,

В приведенном ниже коде KnownParsing функция создает две функции и возвращает их как пару. knownParsingSet затем содержит пары функций, а не экземпляры классов.

Если во вложенном классе есть только один метод, то этот подход прекрасен, потому что один класс метода в основном является просто функцией. Для более чем одного метода в вложенном классе он становится довольно уродливым, и именно поэтому люди F # проблема с использованием других методов. :)

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

5