Megosztás a következőn keresztül:


Osztályok (F#)

Az osztályok olyan típusok, amelyek tulajdonságokat, metódusokat és eseményeket tartalmazó objektumokat jelölnek.

Syntax

// 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 ...
...

Megjegyzések

Az osztályok a .NET-objektumtípusok alapvető leírását képviselik; az osztály az F#-ban az objektumorientált programozást támogató elsődleges típuskoncepció.

Az előző szintaxisban az type-name összes érvényes azonosító. Az type-params opcionális általános típusparamétereket ismerteti. A típusparaméterek neveiből és szögletes zárójelek (< és >) közé zárt megkötésekből áll. További információ: Általános ésmegkötések. A parameter-list konstruktor paramétereit ismerteti. Az első hozzáférési módosító a típusra vonatkozik; a második az elsődleges konstruktorra vonatkozik. Mindkét esetben az alapértelmezett érték.public

Az osztály alaposztályát a inherit kulcsszó használatával adhatja meg. Az alaposztály-konstruktor argumentumait zárójelben kell megadnia.

Kötések használatával let deklarálhatja az osztályhoz helyi mezőket vagy függvényértékeket, és be kell tartania a kötésekre vonatkozó let általános szabályokat. A do-bindings szakasz tartalmazza az objektumépítéskor végrehajtandó kódot.

További member-list konstruktorokból, példány- és statikusmetódus-deklarációkból, felületi deklarációkból, absztrakt kötésekből, valamint tulajdonság- és eseménydeklarációkból áll. Ezeket a képviselők ismertetik.

Az identifier opcionális as kulcsszóval használt név a példány változójának vagy önazonosítójának ad nevet, amely a típusdefinícióban a típuspéldányra hivatkozik. További információt a jelen témakör Önazonosítók című szakaszában talál.

A definíció kezdetét és végét jelző kulcsszavak classend nem kötelezőek.

A kölcsönösen rekurzív típusok, amelyek egymásra hivatkoznak, ugyanúgy vannak összekapcsolva a and kulcsszóval, mint a kölcsönösen rekurzív függvények. Például tekintse meg a kölcsönösen rekurzív típusok című szakaszt.

Konstruktorok

A konstruktor az osztálytípus egy példányát létrehozó kód. Az osztályok konstruktorai némileg másképp működnek F# nyelven, mint más .NET-nyelvekben. Az F#-osztályban mindig van egy elsődleges konstruktor, amelynek argumentumait a parameter-list típusnevet követő szöveg írja le, és amelynek törzse az let osztálydeklaráció elején lévő (és let rec) kötésekből és az do azt követő kötésekből áll. Az elsődleges konstruktor argumentumai hatókörben vannak az osztálydeklarációban.

A kulcsszóval new további konstruktorokat is hozzáadhat tag hozzáadásához az alábbiak szerint:

new(argument-list) = constructor-body

Az új konstruktor törzsének meg kell hívnia az osztálydeklaráció tetején megadott elsődleges konstruktort.

Az alábbi példa ezt a fogalmat szemlélteti. Az alábbi kódban MyClass két konstruktor található, egy elsődleges konstruktor, amely két argumentumot és egy másik konstruktort használ, amelyek nem vesznek fel argumentumokat.

type MyClass1(x: int, y: int) =
    do printfn "%d %d" x y
    new() = MyClass1(0, 0)

Kötések használata és használata

Az let osztálydefiníciók és do kötések alkotják az elsődleges osztálykonstruktor törzsét, ezért az osztálypéldányok létrehozásakor futnak. Ha egy let kötés függvény, akkor a függvény egy taggá lesz lefordítva. Ha a let kötés egy függvényben vagy tagban nem használt érték, akkor a rendszer a konstruktor számára helyi változóvá állítja össze. Ellenkező esetben az osztály egy mezőjébe lesz lefordítva. Az do alábbi kifejezések az elsődleges konstruktorba vannak lefordítva, és inicializálási kódot hajtanak végre minden példányhoz. Mivel minden további konstruktor mindig az elsődleges konstruktort hívja meg, a let kötések és do kötések mindig végrehajtásra kerülnek, függetlenül attól, hogy melyik konstruktort hívják meg.

A kötések által let létrehozott mezők az osztály metódusai és tulajdonságai között érhetők el, azonban statikus metódusokból nem érhetők el, még akkor sem, ha a statikus metódusok paraméterként egy példányváltozót használnak. Ha létezik ilyen, az önazonosítóval nem érhetők el.

Önazonosítók

Az önazonosító az aktuális példányt jelképező név. Az önazonosítók a this C# vagy a C++ Me vagy a Visual Basic kulcsszóra hasonlítanak. Az önazonosítót kétféleképpen határozhatja meg attól függően, hogy az önazonosító a teljes osztálydefiníció hatókörébe tartozik-e, vagy csak egy adott metódusra.

Az egész osztály önazonosítójának meghatározásához használja a as konstruktorparaméter-lista záró zárójelei utáni kulcsszót, és adja meg az azonosító nevét.

Ha csak egy metódushoz szeretne önazonosítót definiálni, adja meg az önazonosítót a tagdeklarációban, a metódus neve előtt, elválasztóként pedig egy pontot (.).

Az alábbi példakód bemutatja az önazonosítók létrehozásának két módját. Az első sorban a as kulcsszó az önazonosító meghatározására szolgál. Az ötödik sorban az azonosító this egy olyan önazonosító meghatározására szolgál, amelynek hatóköre a metódusra PrintMessagekorlátozódik.

type MyClass2(dataIn) as self =
    let data = dataIn
    do
        self.PrintMessage()
    member this.PrintMessage() =
        printf "Creating MyClass2 with Data %d" data

Más .NET-nyelvektől eltérően tetszés szerint nevezheti el az önazonosítót; nem korlátozódik az olyan nevekre, mint a self, Mevagy this.

A kulcsszóval deklarált önazonosító csak az as alapkonstruktor után lesz inicializálva. Ezért az alapkonstruktor System.InvalidOperationException: The initialization of an object or value resulted in an object or value being accessed recursively before it was fully initialized. előtt vagy belsejében való használat esetén a futásidőben emeljük ki. Az önazonosítót az alapkonstruktor után szabadon használhatja, például kötésekben let vagy do kötésekben.

Általános típusparaméterek

Az általános típusparaméterek szögletes zárójelekben (< és >) vannak megadva egyetlen idézőjel és egy azonosító formájában. Több általános típusparamétert vessző választ el egymástól. Az általános típusparaméter hatókörben van a deklaráció során. Az alábbi kód példája az általános típusparaméterek megadását mutatja be.

type MyGenericClass<'a>(x: 'a) =
    do printfn "%A" x

A típus argumentumai a típus használatakor következtetnek. Az alábbi kódban a kikövetkeztetett típus a csuplok sorozata.

let g1 = MyGenericClass(seq { for i in 1..10 -> (i, i * i) })

Öröklés megadása

A inherit záradék azonosítja a közvetlen alaposztályt, ha van ilyen. Az F#-ban csak egy közvetlen alaposztály engedélyezett. Az osztály által implementálható felületek nem tekinthetők alaposztálynak. A felületeket az Interfészek témakör ismerteti.

Az alaposztály metódusait és tulajdonságait a származtatott osztályból úgy érheti el, hogy a nyelvi kulcsszót base azonosítóként használja, majd egy pontot (.) és a tag nevét.

További információ: Öröklés.

Tagok szakasz

Ebben a szakaszban statikus vagy példánymódszereket, tulajdonságokat, felületi implementációkat, absztrakt tagokat, eseménydeklarációkat és további konstruktorokat határozhat meg. Nem jelenhetnek meg kötések ebben a szakaszban. Mivel a tagok az osztályok mellett számos F#-típushoz is hozzáadhatók, egy külön témakörben, a Tagokban tárgyaljuk őket.

Kölcsönösen rekurzív típusok

Ha körkörösen hivatkozó típusokat határoz meg, a kulcsszóval együtt sztringezi a and típusdefiníciókat. A and kulcsszó a kulcsszót az type első definíció kivételével az alábbiak szerint cseréli le.

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

A kimenet az aktuális könyvtárban lévő összes fájl listája.

Mikor érdemes osztályokat, szakszervezeteket, rekordokat és struktúrákat használni?

A választható típusok sokfélesége miatt tisztában kell legyen azzal, hogy az egyes típusokat hogyan tervezték az adott helyzethez megfelelő típus kiválasztásához. Az osztályok objektumorientált programozási környezetekben való használatra lettek tervezve. Az objektumorientált programozás a .NET-keretrendszer írt alkalmazásokban használt domináns paradigma. Ha az F#-kódnak szorosan együtt kell működnie a .NET-keretrendszer vagy egy másik objektumorientált kódtárral, és különösen akkor, ha egy objektumorientált típusú rendszerből, például egy felhasználói felületi kódtárból kell kiterjeszteni, az osztályok valószínűleg megfelelőek.

Ha nem szorosan együttműködik az objektumorientált kódokkal, vagy ha önálló kódot ír, és így védve van az objektumorientált kódokkal való gyakori interakciótól, érdemes megfontolnia az osztályok, rekordok és diszkriminált egyesítések kombinációjának használatát. Az egyetlen, jól átgondolt diszkriminált egyesítés és a megfelelő mintamegfeleltetési kód gyakran használható az objektumhierarchiák egyszerűbb alternatívájaként. A diszkriminált szakszervezetekről további információt a diszkriminált szakszervezetek című témakörben talál.

A rekordok előnye, hogy egyszerűbbek, mint az osztályok, de a rekordok nem megfelelőek, ha egy típus követelményei túllépik az egyszerűségüket. A rekordok alapvetően egyszerű értékek aggregátumai, különálló konstruktorok nélkül, amelyek egyéni műveleteket hajthatnak végre rejtett mezők nélkül, öröklés vagy felületi implementációk nélkül. Bár a tagok, például a tulajdonságok és a metódusok hozzáadhatók a rekordokhoz a viselkedésük összetettebbé tétele érdekében, a rekordban tárolt mezők továbbra is az értékek egyszerű összesítése. A rekordokról további információt a Rekordok című témakörben talál.

A struktúrák kis adatösszesítésekhez is hasznosak, de különböznek az osztályoktól és a rekordoktól abban, hogy .NET-értéktípusok. Az osztályok és rekordok .NET-referenciatípusok. Az értéktípusok és referenciatípusok szemantikája abban különbözik, hogy az értéktípusokat érték adja át. Ez azt jelenti, hogy bitre másolják őket, amikor paraméterként adják át őket, vagy egy függvényből adják vissza őket. A rendszer a veremen is tárolja őket, vagy ha mezőként használják őket, a szülőobjektumba ágyazzák be őket ahelyett, hogy a halom saját különálló helyén lennének tárolva. Ezért a struktúrák megfelelőek a gyakran használt adatokhoz, ha a halom elérésének többletterhelése problémát jelent. További információ a struktúrákról: Structs.

Lásd még