2016-01-25 12 views
5

Mam klasę Java i muszę napisać podobną w języku F #. Jak zdefiniować prywatną klasę publiczną w języku f #?f # prywatna klasa publiczna

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

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

[F # nie obsługuje klasy zagnieżdżanie] (http://stackoverflow.com/questions/8948332/why-doesnt-f-support-nested-classes). – vcsjones

+2

W programowaniu funkcjonalnym myśli się najpierw funkcje, w OO myśli się obiekty najpierw. Myślicie o przedmiocie, kiedy powinniście myśleć o funkcji. Pomyśl, jak utworzyć publiczny rekord funkcji(), który ma ukrytą funkcję KnownParsing(). Funkcja wewnątrz innej funkcji jest zasadniczo prywatna. –

+3

Dlaczego wszystkie głosy na dół? To brzmi jak rozsądne pytanie. – Mathias

Odpowiedz

7

Jest to całkowicie możliwe w języku F #. F # działa najpierw, nie jest czysto funkcjonalny - i jest to jedna z jego głównych zalet. F # jest pragmatyczny i ta konstrukcja poniżej pozwala osiągnąć dokładnie taki sam wynik, nawet jeśli typ KnownParsing nie jest "zagnieżdżony" w języku Java lub 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 są przydatne do realizacji interfejsów lub klasy abstrakcyjne, ale klasa „rodzic” (ten, który tworzy wyrażenie Object) nie będzie w stanie uzyskać dostęp do jego wnętrzności. Lub, bardziej poprawnie, nie ma sposobu na tworzenie elementów wewnętrznych innych niż elementy interfejsu/abstrakcyjne w jakikolwiek inny sposób poza komórkami ref poza samym wyrażeniem obiektu. Ma to wpływ na wydajność, taki jak ciśnienie GC dla komórek ref.

Zobacz przykład z mojego projektu open-source o tym, jak wyrażenia obiektów i typy "zagnieżdżone przez" działają zamiennie dla implementacji IEnumerator. Na this line używam typu private jak w tej odpowiedzi i działa dobrze. W całym projekcie używam F # głównie w sposób imperatywny, ponieważ jest to jedyny sposób na uzyskanie przyzwoitej wydajności. I muszę powiedzieć, że najbardziej lubię F # ponad C# nawet dla imperatywnego kodu.

+0

Wielkie dzięki za odpowiedź! –

5

Jak już mówiono, F # obecnie nie obsługuje klas zagnieżdżonych.

Jedno obejście jest takie, jak pokazuje V.B., z dwiema oddzielnymi klasami, z których jedna jest prywatna.

Jeśli jednak wewnętrzna klasa jest prosta (tylko z jedną lub dwiema metodami), istnieje alternatywne podejście, , które ma używać zamknięcia jako poor-person's object. W poniższym kodzie funkcja tworzy dwie funkcje i zwraca je jako parę. Wówczas knownParsingSet zawiera pary funkcji, a nie wystąpienia klas.

Jeśli w klasie zagnieżdżonej jest tylko jedna metoda, to podejście jest w porządku, ponieważ jedna klasa metod jest po prostu funkcją. Dla więcej niż jednej metody w klasie zagnieżdżonej staje się dość brzydka, dlatego F # ludzie rozwiązują problem z użyciem innych technik. :)

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

Dodatkowe alokacje tylko po to, aby być czystym - tuple + 2 Funki przynajmniej, bez żadnej nadziei na inlinowanie przez Jit. Pozwolę sobie po prostu zrozumieć, dlaczego tak wielu użytkowników F # jest przeciwko znacznie prostszym rozwiązaniom na rzecz puryzmu? To pytanie prześladuje mnie od 2 lat. –

+0

Pytanie nie dotyczyło wydajności, tylko sposobu implementacji zagnieżdżonych klas. Na pewno nie twierdziłbym, że jest to optymalne rozwiązanie! Właśnie pokazałem alternatywne rozwiązanie dla PO. – Grundoon

+0

@ V.B. Dla mnie jest tak, że kod funkcjonalny jest bardziej prawdopodobny, gdy jest czysto funkcjonalny. Gdyby inne czyste języki funkcyjne, takie jak [ML] (https://en.wikipedia.org/wiki/ML_ (programming_language)) stały się bardziej głównym strumieniem i miały lepsze narzędzia i wsparcie, użyłbym ich zamiast tego. Gdyby [Coq] (https://coq.inria.fr/) mógł zostać użyty jako język programowania, użyłbym tego. Gdyby [Mercury] (https://mercurylang.org/) był bardziej powszechny i ​​miał lepsze narzędzia, użyłbym tego. Opieram się także na [Algebraic Data Types] (https://en.wikipedia.org/wiki/Algebraic_data_type) i tak pogardzam, jeśli oświadczenia: –

Powiązane problemy