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


Konstruktorok

Ez a cikk azt ismerteti, hogyan definiálhat és használhat konstruktorokat osztály- és struktúraobjektumok létrehozására és inicializálására.

Osztályobjektumok felépítése

Az osztálytípusok objektumai konstruktorokkal rendelkeznek. Kétféle konstruktor létezik. Az egyik az elsődleges konstruktor, amelynek paraméterei zárójelben jelennek meg a típus neve után. A kulcsszó használatával new további, opcionális konstruktorokat is megadhat. Minden ilyen további konstruktornak meg kell hívnia az elsődleges konstruktort.

Az elsődleges konstruktor az osztálydefiníció elején megjelenő kötéseket tartalmazza és do kötilet. A let kötés az osztály privát mezőit és metódusait deklarálja, a do kötés pedig kódot hajt végre. További információ az osztálykonstruktorok kötéseiről let : let Kötések az osztályokban. A konstruktorok kötéseiről további információt do az osztályok kötései című témakörben találdo.

Függetlenül attól, hogy a meghívni kívánt konstruktor elsődleges konstruktor vagy további konstruktor, létrehozhat objektumokat egy new kifejezéssel, az opcionális new kulcsszóval vagy anélkül. Az objektumokat konstruktorargumentumokkal együtt inicializálhatja az argumentumok sorrendbe sorolásával, vesszővel elválasztva és zárójelben elválasztva, vagy elnevezett argumentumok és értékek zárójelben való használatával. Az objektumon a tulajdonságokat a tulajdonságnevek használatával és az értékek hozzárendelésével is beállíthatja az objektumon, ahogyan a nevesített konstruktorargumentumokat használja.

Az alábbi kód egy konstruktort tartalmazó osztályt és az objektumok létrehozásának különböző módjait mutatja be:

// This class has a primary constructor that takes three arguments
// and an additional constructor that calls the primary constructor.
type MyClass(x0, y0, z0) =
    let mutable x = x0
    let mutable y = y0
    let mutable z = z0
    do
        printfn "Initialized object that has coordinates (%d, %d, %d)" x y z
    member this.X with get() = x and set(value) = x <- value
    member this.Y with get() = y and set(value) = y <- value
    member this.Z with get() = z and set(value) = z <- value
    new() = MyClass(0, 0, 0)

// Create by using the new keyword.
let myObject1 = new MyClass(1, 2, 3)
// Create without using the new keyword.
let myObject2 = MyClass(4, 5, 6)
// Create by using named arguments.
let myObject3 = MyClass(x0 = 7, y0 = 8, z0 = 9)
// Create by using the additional constructor.
let myObject4 = MyClass()

A kimenet a következő:

Initialized object that has coordinates (1, 2, 3)
Initialized object that has coordinates (4, 5, 6)
Initialized object that has coordinates (7, 8, 9)
Initialized object that has coordinates (0, 0, 0)

Szerkezetek felépítése

A struktúrák az osztályok minden szabályát követik. Ezért rendelkezhet elsődleges konstruktorsal, és további konstruktorokat is megadhat a használatával new. A struktúrák és osztályok között azonban van egy fontos különbség: a struktúrák paraméter nélküli konstruktorsal (vagyis argumentumok nélkül) rendelkezhetnek akkor is, ha nincs meghatározva elsődleges konstruktor. A paraméter nélküli konstruktor inicializálja az összes mezőt az adott típus alapértelmezett értékére, általában nulla vagy azzal egyenértékű értékre. A struktúrákhoz definiált konstruktoroknak legalább egy argumentummal kell rendelkezniük, hogy ne ütközhessenek a paraméter nélküli konstruktorral.

A struktúrákban gyakran vannak olyan mezők is, amelyek a val kulcsszó használatával jönnek létre; az osztályok is tartalmazhatnak ilyen mezőket. A kulcsszóval val definiált mezőkkel rendelkező struktúrák és osztályok további konstruktorokban is inicializálhatók rekordkifejezések használatával, ahogyan az az alábbi kódban is látható.

type MyStruct =
    struct
       val X : int
       val Y : int
       val Z : int
       new(x, y, z) = { X = x; Y = y; Z = z }
    end

let myStructure1 = new MyStruct(1, 2, 3)

További információ: Explicit mezők: A val kulcsszó.

Mellékhatások végrehajtása konstruktorokban

Az osztály elsődleges konstruktorai kódot hajthatnak végre egy do kötésben. Mi a teendő azonban, ha egy további konstruktorban, kötés nélkül kell végrehajtania a do kódot? Ehhez a kulcsszót then kell használnia.

 // Executing side effects in the primary constructor and
// additional constructors.
type Person(nameIn : string, idIn : int) =
    let mutable name = nameIn
    let mutable id = idIn
    do printfn "Created a person object."
    member this.Name with get() = name and set(v) = name <- v
    member this.ID with get() = id and set(v) = id <- v
    new() =
        Person("Invalid Name", -1)
        then
            printfn "Created an invalid person object."

let person1 = new Person("Humberto Acevedo", 123458734)
let person2 = new Person()

Az elsődleges konstruktor mellékhatásai még mindig végrehajtásra várnak. Ezért a kimenet a következő:

Created a person object.
Created a person object.
Created an invalid person object.

then A másik do helyett azért van szükség rá, mert a do kulcsszó szabványos jelentése egy unit-returning kifejezés elválasztása, ha egy további konstruktor törzsében jelen van. Csak az elsődleges konstruktorok kontextusában különleges jelentéssel rendelkezik.

Önazonosítók konstruktorokban

A többi tagban az egyes tagok definíciójában adja meg az aktuális objektum nevét. Az önazonosítót az osztálydefiníció első sorára is elhelyezheti a as konstruktorparamétereket közvetlenül követő kulcsszó használatával. Az alábbi példa ezt a szintaxist szemlélteti.

type MyClass1(x) as this =
    // This use of the self identifier produces a warning - avoid.
    let x1 = this.X
    // This use of the self identifier is acceptable.
    do printfn "Initializing object with X =%d" this.X
    member this.X = x

További konstruktorokban önazonosítót is definiálhat, ha közvetlenül a as konstruktorparaméterek után helyezi el a záradékot. Az alábbi példa ezt a szintaxist szemlélteti:

type MyClass2(x : int) =
    member this.X = x
    new() as this = MyClass2(0) then printfn "Initializing with X = %d" this.X

Problémák léphetnek fel, ha egy objektumot a teljes definiálás előtt próbál használni. Ezért az önazonosító használata miatt a fordító figyelmeztetést ad ki, és további ellenőrzéseket szúr be annak érdekében, hogy az objektum tagjai ne férjenek hozzá az objektum inicializálása előtt. Az önazonosítót csak az do elsődleges konstruktor kötéseiben vagy a then további konstruktorok kulcsszója után szabad használni.

Az önazonosító nevének nem kell lennie this. Bármilyen érvényes azonosító lehet.

Értékek hozzárendelése tulajdonságokhoz inicializáláskor

Az inicializálási kódban egy osztályobjektum tulajdonságaihoz rendelhet értékeket úgy, hogy hozzáfűzi az űrlap property = value hozzárendeléseinek listáját egy konstruktor argumentumlistájához. Ez a következő kód példában látható:

 type Account() =
    let mutable balance = 0.0
    let mutable number = 0
    let mutable firstName = ""
    let mutable lastName = ""
    member this.AccountNumber
       with get() = number
       and set(value) = number <- value
    member this.FirstName
       with get() = firstName
       and set(value) = firstName <- value
    member this.LastName
       with get() = lastName
       and set(value) = lastName <- value
    member this.Balance
       with get() = balance
       and set(value) = balance <- value
    member this.Deposit(amount: float) = this.Balance <- this.Balance + amount
    member this.Withdraw(amount: float) = this.Balance <- this.Balance - amount


let account1 = new Account(AccountNumber=8782108,
                           FirstName="Darren", LastName="Parker",
                           Balance=1543.33)

Az előző kód alábbi verziója a szokásos argumentumok, választható argumentumok és tulajdonságbeállítások kombinációját mutatja be egy konstruktorhívásban:

type Account(accountNumber : int, ?first: string, ?last: string, ?bal : float) =
   let mutable balance = defaultArg bal 0.0
   let mutable number = accountNumber
   let mutable firstName = defaultArg first ""
   let mutable lastName = defaultArg last ""
   member this.AccountNumber
      with get() = number
      and set(value) = number <- value
   member this.FirstName
      with get() = firstName
      and set(value) = firstName <- value
   member this.LastName
      with get() = lastName
      and set(value) = lastName <- value
   member this.Balance
      with get() = balance
      and set(value) = balance <- value
   member this.Deposit(amount: float) = this.Balance <- this.Balance + amount
   member this.Withdraw(amount: float) = this.Balance <- this.Balance - amount


let account1 = new Account(8782108, bal = 543.33,
                          FirstName="Raman", LastName="Iyer")

Konstruktorok az örökölt osztályban

Ha konstruktort tartalmazó alaposztályból örököl, az öröklési záradékban meg kell adnia az argumentumait. További információ: Konstruktorok és öröklés.

Statikus konstruktorok vagy típuskonstruktorok

Az objektumok létrehozásához szükséges kód megadása mellett a statikus let és do kötések olyan osztálytípusokban is létrehozhatók, amelyek a típus első használata előtt végrehajtják az inicializálást a típus szintjén. További információ: let Kötések osztályokban és do kötések az osztályokban.

Lásd még