Klasy (F#)
Klasy są typy, które reprezentują obiektów, które mogą mieć właściwości, metod i zdarzeń.
// Class definition:
type [access-modifier] type-name [type-params] [access-modifier] ( parameter-list ) [ as identifier ] =
[ class ]
[ inherit base-type-name(base-constructor-args) ]
[ let-bindings ]
[ do-bindings ]
member-list
...
[ end ]
// Mutually recursive class definitions:
type [access-modifier] type-name1 ...
and [access-modifier] type-name2 ...
...
Uwagi
Klasy reprezentują opis podstawowych.Typy obiektów netto; Klasa jest koncepcja typu podstawowego, obsługujący programowanie zorientowane obiektowo w języku F#.
W poprzednim składni type-name jest dowolnym prawidłowym identyfikatorem.type-params w tym artykule opisano parametry opcjonalne typu rodzajowego.Składa się z nazwy parametrów typu i ograniczeń, ujęte w nawiasy ostre (< i >).Aby uzyskać więcej informacji, zobacz Typy ogólne (F#) i Ograniczenia (F#).parameter-list w tym artykule opisano parametry konstruktora.Modyfikator dostępu pierwszy dotyczy typu; Druga odnosi się do podstawowego konstruktora.W obu przypadkach, wartością domyślną jest public.
Określ klasą bazową dla klasy za pomocą inherit słowa kluczowego.Należy podać argumenty w nawiasach, do konstruktora klasy podstawowej.
Zadeklarować pola lub wartości, które są lokalne do klasy przy użyciu działać let wiązania, a należy wykonać ogólne zasady let wiązania.do-bindings Sekcja zawiera kod do wykonania przy budowa obiektu.
member-list Składa się z konstruktory dodatkowe, instancji i statyczna metoda deklaracje, deklaracje interfejsu, abstrakcyjna wiązania i deklaracji właściwości i zdarzeń.Są one opisane w Członkowie (F#).
identifier , Jest używany z opcjonalnej as słowa kluczowego nadaje nazwę zmiennej instancji lub self identyfikator, który może służyć w definicji typu do odwoływania się do wystąpienia tego typu.Aby uzyskać więcej informacji zobacz sekcję Self identyfikatory w dalszej części tego tematu.
Słowa kluczowe class i end , oznaczyć początek i koniec definicji są opcjonalne.
Wzajemnie połączonych rodzajów cykliczne, które są typy, które odwołują się do siebie, wraz z and słowa kluczowego, podobnie jak wzajemnie są rekurencyjne funkcji.Na przykład zobacz sekcję wzajemnie typów cykliczne.
Konstruktory
Konstruktora jest kodem, który tworzy wystąpienie typu klasy.Konstruktory klas działa nieco inaczej w F# niż w innych.Języki netto.F# klasy, zawsze istnieje podstawowy konstruktora, której argumenty są opisane w parameter-list wynika, wpisz nazwę i którego organ składa się z let (i let rec) wiązania na początku deklaracji klasy oraz do powiązań, które należy wykonać.Argumenty konstruktora podstawowego są w zakresie całej deklaracji klasy.
Konstruktory dodatkowe można dodać za pomocą new słowo kluczowe, aby dodać członka, w następujący sposób:
new(argument-list) = constructor-body
Jednostka konstruktora new należy wywołać konstruktora podstawowego, który jest określony w górnej części deklaracji klasy.
Poniższy przykład ilustruje tę koncepcję.W poniższym kodzie MyClass ma dwa konstruktory, Konstruktor podstawowego, który ma dwa argumenty i innego konstruktora, który nie przyjmuje żadnych argumentów.
type MyClass1(x: int, y: int) =
do printfn "%d %d" x y
new() = MyClass1(0, 0)
Niech i wykonać powiązania
let i do wiązania w definicji klasy formularza treści konstruktora klasy podstawowej, a więc uruchamiać gdy tworzona jest instancja klasy.Jeśli let powiązania jest funkcją, a następnie jest skompilowany do członka.Jeśli let powiązanie jest wartość, która nie jest używany w jakichkolwiek funkcji lub członka, a następnie jest skompilowany do zmiennej lokalnej dla konstruktora.W przeciwnym razie jest skompilowany w polu Klasa.do Wyrażeń, które należy wykonać, są skompilowane w konstruktorze podstawowego i wykonanie kodu inicjowania dla każdego wystąpienia.Ponieważ wszelkie dodatkowe konstruktory zawsze używaj wywołania konstruktora podstawowego let powiązania i do wiązania wykonać zawsze, niezależnie od tego, które konstruktora jest nazywany.
Pola, które są tworzone przez let powiązania jest możliwy całej metody i właściwości klasy; Jednakże one nie są dostępne z metody statyczne, nawet jeśli metody statyczne zmiennej instancji, jako parametr.Te nie są dostępne przy użyciu identyfikatora self, jeśli taki istnieje.
Self identyfikatory
A self identyfikator jest nazwą, która reprezentuje bieżącą instancję.Identyfikatory Self przypominają this słowa kluczowego w C# lub C++ lub Me w języku Visual Basic.Można zdefiniować własny identyfikator na dwa różne sposoby, w zależności od tego, czy chcesz samodzielnie identyfikator w zakres definicji całej klasy lub tylko dla indywidualnej metody.
Aby zdefiniować własny identyfikator dla całej klasy, użyj as słowa kluczowego po zamykającym nawiasem kwadratowym parametru konstruktora listy, a następnie określ nazwę identyfikatora.
Aby zdefiniować własny identyfikator dla tylko jednej metody, zapewniają self identyfikator w deklaracji członka, tuż przed nazwą metody i kropki (.) jako separator.
Poniższy przykład kodu ilustruje dwa sposoby, aby utworzyć własny identyfikator.W pierwszym wierszu as słowo kluczowe jest używany do definiowania self identyfikator.W wierszu piątym identyfikator this jest używana do definiowania self identyfikator, którego zakres jest ograniczony do metody PrintMessage.
type MyClass2(dataIn) as self =
let data = dataIn
do
self.PrintMessage()
member this.PrintMessage() =
printf "Creating MyClass2 with Data %d" data
W odróżnieniu od innych.NET języków, można nadać nazwę self identyfikator jednak chcesz; są nie do zostanie ograniczony nazwy takie jak self, Me, lub this.
Identyfikator self, która jest zadeklarowana z as słowa kluczowego nie został zainicjowany aż po let powiązania są wykonywane.W związku z tym, nie mogą być używane w let wiązania.Można użyć identyfikatora self w do sekcji wiązania.
Parametry typu rodzajowego
Określono parametr typu rodzajowego w nawiasy ostre (< i >), w formie pojedynczego cudzysłowu następuje identyfikator.Wiele parametrów typu rodzajowego są oddzielone przecinkami.Parametr typu rodzajowego jest w zakresie całego zgłoszenia.Poniższy przykład kodu pokazuje sposób określić parametry typu rodzajowego.
type MyGenericClass<'a> (x: 'a) =
do printfn "%A" x
Gdy używany jest typ, są wywnioskować argumentów typu.W poniższym kodzie nie powiązano typu jest sekwencja krotek.
let g1 = MyGenericClass( seq { for i in 1 .. 10 -> (i, i*i) } )
Określanie dziedziczenia
inherit Klauzuli identyfikuje bezpośrednia klasa podstawowa, jeśli istnieje.F# jest dozwolony tylko jeden bezpośrednia klasa podstawowa.Interfejsy, które implementuje klasy nie są uważane za klas podstawowych.Interfejsy zostały omówione w Interfejsy (F#) tematu.
Z klasy pochodnej można dostępu metod i właściwości klasy podstawowej za pomocą słowa kluczowego języka base jako identyfikator, następuje kropka (.) i nazwa elementu członkowskiego.
Aby uzyskać więcej informacji, zobacz Dziedziczenie (F#).
Sekcję członków
W tej sekcji można zdefiniować static lub metody instancji, właściwości, implementacje interfejsu, abstract członków, deklaracje zdarzeń i dodatkowe konstruktorów.Niech i wiązania nie wyglądają w tej sekcji.Ponieważ członkowie dodaje się do różnych typów F# oprócz klas, są omówione w osobnym temacie, Członkowie (F#).
Wzajemnie typów cykliczne
Podczas definiowania typów, które odwołują się wzajemnie w sposób cykliczne można string ze sobą definicji typu za pomocą and słowa kluczowego.and Zastępuje słowo kluczowe type słowa kluczowego na wszystkie z wyjątkiem pierwszego definicji, w następujący sposób.
open System.IO
type Folder(pathIn: string) =
let path = pathIn
let filenameArray : string array = Directory.GetFiles(path)
member this.FileArray = Array.map (fun elem -> new File(elem, this)) filenameArray
and File(filename: string, containingFolder: Folder) =
member this.Name = filename
member this.ContainingFolder = containingFolder
let folder1 = new Folder(".")
for file in folder1.FileArray do
printfn "%s" file.Name
Dane wyjściowe znajduje się lista wszystkich plików w bieżącym katalogu.
Kiedy należy używać klas, związki, rekordów i struktur
Biorąc pod uwagę różnych typów, które można wybierać, trzeba mieć dobre zrozumienie, co każdy typ jest przeznaczony do wybierz odpowiedni typ dla szczególnej sytuacji.Klas są przeznaczone do wykorzystania w kontekście programowania obiektowego.Programowanie zorientowane obiektowo jest dominującą paradygmat używany w aplikacjach, które są napisane dla.NET Framework.Jeśli kod F# musi ściśle współpracować z.NET Framework lub innej biblioteki zorientowane obiektowo, a zwłaszcza, jeśli masz rozciągają się od systemu typu object-oriented, takich jak biblioteka interfejsu użytkownika, klas są prawdopodobnie odpowiedni.
Jeśli użytkownik nie są ściśle współdziałanie z kodem object-oriented lub pisania kodu, który jest niezależnym i dlatego chronione przed częste interakcji z kodem zorientowane obiektowo, należy wziąć pod uwagę przy użyciu rekordów i izolowanie związków.Thought–out pojedynczy, także izolowanie Unii, wraz z odpowiedni wzorzec dopasowania kodu, często mogą być używane jako prostsze alternatywę dla hierarchii obiektów.Aby uzyskać więcej informacji na temat związków dyskryminowanych zobacz Sumy rozłączne (F#).
Rekordy mają tę zaletę jest prostsze niż klas, ale rekordy nie są odpowiednie, gdy zapotrzebowanie typu przekracza, co można zrobić z ich uproszczenia.Rekordy są zasadniczo proste zagregowanych wartości, bez konstruktory oddzielnych, które można wykonywać akcje niestandardowe, bez ukrytych pól i bez implementacje dziedziczenia lub interfejsu.Pola, przechowywanych w rekordzie, chociaż członków, takie jak właściwości i metody dodaje się do rekordów, aby ich zachowanie bardziej złożone, są nadal proste suma wartości.Aby uzyskać więcej informacji o rekordach, zobacz Rekordy (F#).
Budowle są także przydatne do małych zagregowanych danych, ale różnią się od klas i rekordy są.Typy wartości netto.Klasy i rekordy są.Typy odwołań netto.Semantyka typów wartości i typy odwołań są różne, w tym typów wartości są przekazywane przez wartość.Oznacza to, że są one kopiowane bit bitu, gdy są one przekazane jako parametr lub zwrócone przez funkcję.Są również przechowywane na stosie lub, jeśli są one używane jako pole osadzonego obiektu nadrzędnego, zamiast przechowywane w ich własnych innej lokalizacji na stercie.W związku z tym struktury są odpowiednie dla najczęściej używanych danych, gdy obciążenie związane z dostęp do sterty jest problem.Aby uzyskać więcej informacji na temat struktury, zobacz Struktury (F#).