Konstruktor
Artikel ini menjelaskan cara menentukan dan menggunakan konstruktor untuk membuat dan menginisialisasi objek kelas dan struktur.
Konstruksi objek kelas
Objek dari jenis kelas memiliki konstruktor. Ada dua jenis konstruktor. Salah satunya adalah konstruktor utama, yang parameternya muncul dalam tanda kurung tepat setelah nama jenis. Anda menentukan konstruktor tambahan opsional lainnya dengan menggunakan kata kunci new
. Setiap konstruktor tambahan tersebut harus memanggil konstruktor utama.
Konstruktor utama berisi pengikatan let
dan do
yang muncul di awal definisi kelas. Pengikatan let
mendeklarasikan bidang privat dan metode kelas; pengikatan do
menjalankan kode. Untuk informasi selengkapnya tentang pengikatan let
di konstruktor kelas, lihat Pengikatan let
di Kelas. Untuk informasi selengkapnya tentang pengikatan do
dalam konstruktor, lihat Pengikatan do
di Kelas.
Terlepas dari apakah konstruktor yang ingin Anda panggil adalah konstruktor utama atau konstruktor tambahan, Anda dapat membuat objek dengan menggunakan ekspresi new
, dengan atau tanpa kata kunci new
opsional. Anda menginisialisasi objek Anda bersama dengan argumen konstruktor, baik dengan membuat daftar argumen secara berurutan, dipisahkan oleh koma, dan diapit dengan 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 seperti Anda menggunakan argumen konstruktor bernama.
Kode berikut menggambarkan 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 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, yang tidak memiliki 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 kali memiliki bidang yang dibuat dengan menggunakan kata kunci val
; kelas juga dapat memiliki bidang ini. Struktur dan kelas yang memiliki bidang, yang ditentukan dengan menggunakan kata kunci val
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 Kunci val
.
Menjalankan efek samping dalam konstruktor
Sebuah konstruktor utama di sebuah kelas dapat menjalankan kode dalam pengikatan do
. Namun, bagaimana jika Anda harus menjalankan kode dalam konstruktor tambahan, tanpa pengikatan do
? Untuk melakukannya, Anda menggunakan kata kunci then
.
// 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, output-nya adalah sebagai berikut:
Created a person object.
Created a person object.
Created an invalid person object.
Alasan mengapa then
dibutuhkan ali-alih do
lainnya adalah karena kata kunci do
memiliki arti standar membatasi ekspresi pengembalian unit
ketika ada di isi konstruktor tambahan. Hal tersebut 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 kata kunci as
segera setelah parameter konstruktor. Contoh berikut menggambarkan 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 mandiri dengan menempatkan klausul as
tepat setelah parameter konstruktor. Contoh berikut menggambarkan 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 untuk menggunakan objek sebelum objek tersebut sepenuhnya ditentukan. Oleh karena itu, penggunaan pengidentifikasi mandiri dapat menyebabkan kompilator mengeluarkan peringatan dan menyisipkan pemeriksaan tambahan untuk memastikan anggota objek tidak diakses sebelum objek tersebut diinisialisasi. Anda hanya boleh menggunakan pengidentifikasi mandiri dalam pengikatan do
dari konstruktor utama atau setelah kata kunci then
di konstruktor tambahan.
Nama pengidentifikasi mandiri tidak harus this
. Namanya dapat berupa pengidentifikasi apa pun 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. Hal 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 ini menggambarkan 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 diwarisi
Saat mewarisi dari kelas dasar yang memiliki konstruktor, Anda harus menentukan argumennya dalam klausul pewarisan. Untuk informasi selengkapnya, lihat Konstruktor dan warisan.
Konstruktor statis atau konstruktor jenis
Selain menentukan kode untuk membuat objek, pengikatan let
dan do
statis dapat ditulis dalam jenis kelas yang dijalankan sebelum jenis tersebut digunakan untuk melakukan inisialisasi pada tingkat jenis. Untuk informasi selengkapnya, lihat Pengikatan let
di Kelas dan Pengikatan do
di Kelas.
Lihat juga
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk