Bagikan melalui


Konstruktor

Artikel ini menjelaskan cara menentukan dan menggunakan konstruktor untuk membuat dan menginisialisasi objek kelas dan struktur.

Konstruksi objek kelas

Objek jenis kelas memiliki konstruktor. Ada dua jenis konstruktor. Salah satunya adalah konstruktor utama, yang parameternya muncul dalam tanda kurung tepat setelah nama jenis. Secara opsional, Anda dapat menentukan konstruktor tambahan dengan menggunakan new kata kunci. Setiap konstruktor tambahan tersebut harus memanggil konstruktor utama.

Konstruktor utama berisi let dan do pengikatan yang muncul di awal definisi kelas. Pengikatan let mendeklarasikan bidang privat dan metode kelas; pengikatan do menjalankan kode. Untuk informasi selengkapnya tentang let pengikatan di konstruktor kelas, lihat let Pengikatan di Kelas. Untuk informasi selengkapnya tentang do pengikatan dalam konstruktor, lihat do Pengikatan di Kelas.

Terlepas dari apakah konstruktor yang ingin Anda panggil adalah konstruktor utama atau konstruktor tambahan, Anda dapat membuat objek dengan menggunakan new ekspresi, dengan atau tanpa kata kunci opsional new . Anda menginisialisasi objek Anda bersama dengan argumen konstruktor, baik dengan mencantumkan argumen secara berurutan dan dipisahkan oleh koma dan diapit dalam tanda kurung, atau dengan menggunakan argumen dan nilai bernama dalam tanda kurung. Anda juga dapat mengatur properti pada objek selama konstruksi objek dengan menggunakan nama properti dan menetapkan nilai sama seperti Anda menggunakan argumen konstruktor bernama.

Kode berikut mengilustrasikan kelas yang memiliki konstruktor dan berbagai cara membuat objek:

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

Outputnya adalah sebagai berikut:

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)

Konstruksi struktur

Struktur mengikuti semua aturan kelas. Oleh karena itu, Anda dapat memiliki konstruktor utama, dan Anda dapat menyediakan konstruktor tambahan dengan menggunakan new. Namun, ada satu perbedaan penting antara struktur dan kelas: struktur dapat memiliki konstruktor tanpa parameter (yaitu, satu tanpa argumen) bahkan jika tidak ada konstruktor utama yang ditentukan. Konstruktor tanpa parameter menginisialisasi semua bidang ke nilai default untuk jenis tersebut, biasanya nol atau yang setara. Setiap konstruktor yang Anda tentukan untuk struktur harus memiliki setidaknya satu argumen sehingga tidak bertentangan dengan konstruktor tanpa parameter.

Selain itu, struktur sering memiliki bidang yang dibuat dengan menggunakan val kata kunci; kelas juga dapat memiliki bidang ini. Struktur dan kelas yang memiliki bidang yang ditentukan dengan menggunakan val kata kunci juga dapat diinisialisasi dalam konstruktor tambahan dengan menggunakan ekspresi rekaman, seperti yang ditunjukkan dalam kode berikut.

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)

Untuk informasi selengkapnya, lihat Bidang Eksplisit: Kata val Kunci.

Menjalankan efek samping dalam konstruktor

Konstruktor utama dalam kelas dapat menjalankan kode dalam pengikatan do . Namun, bagaimana jika Anda harus menjalankan kode dalam konstruktor tambahan, tanpa do pengikatan? Untuk melakukan ini, Anda menggunakan then kata kunci.

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

Efek samping dari konstruktor utama masih dijalankan. Oleh karena itu, outputnya adalah sebagai berikut:

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

Alasan mengapa then diperlukan alih-alih yang lain do adalah bahwa do kata kunci memiliki arti standar untuk memisahkan unitekspresi -returning ketika ada di isi konstruktor tambahan. Ini hanya memiliki arti khusus dalam konteks konstruktor utama.

Pengidentifikasi mandiri dalam konstruktor

Di anggota lain, Anda memberikan nama untuk objek saat ini dalam definisi setiap anggota. Anda juga dapat menempatkan pengidentifikasi mandiri pada baris pertama definisi kelas dengan menggunakan as kata kunci segera mengikuti parameter konstruktor. Contoh berikut mengilustrasikan sintaks ini.

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

Dalam konstruktor tambahan, Anda juga dapat menentukan pengidentifikasi diri dengan menempatkan as klausul tepat setelah parameter konstruktor. Contoh berikut mengilustrasikan sintaks ini:

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

Masalah dapat terjadi ketika Anda mencoba menggunakan objek sebelum sepenuhnya ditentukan. Oleh karena itu, penggunaan pengidentifikasi mandiri dapat menyebabkan pengkompilasi mengeluarkan peringatan dan menyisipkan pemeriksaan tambahan untuk memastikan anggota objek tidak diakses sebelum objek diinisialisasi. Anda hanya boleh menggunakan pengidentifikasi mandiri dalam do pengikatan konstruktor utama, atau setelah then kata kunci di konstruktor tambahan.

Nama pengidentifikasi diri tidak harus this. Ini bisa menjadi pengidentifikasi yang valid.

Menetapkan nilai ke properti saat inisialisasi

Anda dapat menetapkan nilai ke properti objek kelas dalam kode inisialisasi dengan menambahkan daftar penetapan formulir property = value ke daftar argumen untuk konstruktor. Ini ditunjukkan dalam contoh kode berikut:

 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)

Versi kode sebelumnya berikut mengilustrasikan kombinasi argumen biasa, argumen opsional, dan pengaturan properti dalam satu panggilan konstruktor:

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

Konstruktor di kelas yang diwariskan

Saat mewarisi dari kelas dasar yang memiliki konstruktor, Anda harus menentukan argumennya dalam klausa warisan. Untuk informasi selengkapnya, lihat Konstruktor dan pewarisan.

Konstruktor statis atau konstruktor jenis

Selain menentukan kode untuk membuat objek, statis let dan do pengikatan dapat ditulis dalam jenis kelas yang dijalankan sebelum jenis pertama kali digunakan untuk melakukan inisialisasi pada tingkat jenis. Untuk informasi selengkapnya, lihat let Pengikatan di Kelas dan do Pengikatan di Kelas.

Lihat juga