() translation by (you can also view the original English article)
Di artikel sebelumnya dalam seri ini, kami membahas tentang dasar-dasar bahasa pemrograman Swift. Jika Anda mengikuti tutorial tersebut, sekarang Anda seharusnya sudah memiliki pemahaman yang bagus akan variabel, konstanta, fungsi, dan closure. Sekarang saatnya menggunakan apa yang telah kita pelajari sejauh ini dan mengaplikasikan pengetahuan tersebut ke konsp-konsep berorientasi objek yang ada di Swift.
Untuk memahami konsep yang dibahasa di tutorial ini, penting bagi Anda untuk memiliki pemahamam dasar tentang pemrograman berbasis objek. Jika Anda belum akrab dengan kelas, objek, dan metode, saya sarankan Anda membaca terlebih dahulu topik-topik tersebut sebelum melanjutkan dengan artikel ini.
1. Perkenalan
Di artikel ini, kita akan mengeksplorasi blok bangunan fundamental pemrograman berorientasi objek di Swift, yakni kelas dan struktur. Di Swift, kelas dan struktur terasa dan berperilaku sangat mirip, tetapi ada sejumlah perbedaan utama yang harus Anda pahami untuk menghindari sejumlah perangkap yang umum terjadi.
Di Objective-C, kelas dan struktur sangatlah berbeda. Ini tidak berlaku untuk Swift. Misalnya di Swift, baik kelas maupun struktur bisa memiliki properti dan metode. Tidak seperti struktur C, struktur di Swift bisa diperluas dan diselaraskan ke protokol.
Pertanyaannya adalah "Apa perbedaan antara kelas dan struktur?" Kita akan menyambangi pertanyaan ini di bagian selanjutnya artikel ini. Pertama mari kita lihat seperti apa kelas di Swift.
2. Terminologi
Sebelum mulai bekerja dengan kelas dan struktur, saya ingin mengklarifikasi beberapa istilah yang umumnya digunakan dalam pemrograman berorientasi objek. Istilah kelas, objek, dan instance sering membingungkan orang yang masih baru terhadap pemrograman berorientasi objek dan oleh karenanya penting untuk diketahui bagaimana Swift menggunaan istilah-istilah ini.
Objek dan Instance
Kelas adalah cetak biru atau templat untuk instance kelas tersebut. Istilah objek sering digunakan untuk merujuk pada instance dari suatu kelas. Meskipun demikian, di Swift kelas dan struktur sangatlah mirip dan oleh karenannya lebih mudah dan tidak begitu membingungkan untuk menggunakan istilah instance bagi kelas maupun struktur.
Metode dan Fungsi
Di bagian awal seri ini, kita bekerja dengan beberapa fungsi. Dalam konteks kelas dan struktur, kita bisanya merujuk pada fungsi sebagai metode. Dengan kata lain, metode dan fungsi yang dimiliki oleh kelas atau struktur tertentu. Dalam konteks kelas dan struktur, Anda bisa menggunakan kedua istilah saling menggantikan karena tiap metode adalah fungsi.
3. Mendefinisikan suatu Kelas
Mari memulai perjalanan kita dengan mendefinisikan suatu kelas. Buka Xcode dan ciptakan tempat bermain baru. Hapus konten di tempat bermain itu dan masukkan definisi kelas berikut.
1 |
class Person { |
2 |
|
3 |
}
|
Kata kunci class
mengindikasikan bahwa kita sedang mendefinisikan suatu kelas yang dinamai Person. Implementasi kelas dilingkupi dengan sepasang kurung kurawal. Meskipun kelas Person
tidak begitu bermanfaat dalam bentuknya yang sebenarnya, ini adalah kelas Swift yang benar dan fungsional.
Properti
Sebagaimana di kebanyakan bahasa pemrograman, suatu kelas bisa memiliki properti dan metode. Di contoh yang telah diperbarui di bawah ini, kita mendefinisikan tiga properti:
-
firstName
, suatu properti variabel tipeString?
-
lastName
, suatu properti variabel tipeString?
-
gender
: suatu properti konstantan tipeString
1 |
class Person { |
2 |
var firstName: String? |
3 |
var lastName: String? |
4 |
let gender = "female" |
5 |
}
|
Sebagaimana yang diilustrasikan di contoh, mendefinisikan properti di suatu definisi kelas sangat mirip dengan mendefinisikan variabel dan konstanta reguler. Kita menggunakan kata kunci var
untuk mendefinisikan properti variabel dan kata kunci let
mendefinisikan suatu properti konstanta.
Properti-properti di atas juga dikenal sebagai properti stored. Lebih lanjut di seri ini, kita akan mempelajari tentang properti computed. Sebagaimana disiratkan oleh namanya, properti stored adalah properti yang disimpan oleh instance kelas. Sangat mirip dengan properti-properti di Objective-C.
Penting untuk dicatat bahwa tiap properti yang disimpan harus punya nilai setelah inisialisasi atau didefinisikan sebagai tipe opsional. Di contoh di atas, kita memberikan nilai awal "female"
pada properti gender
. Ini memberitahu Swift bahwa properti gendernya adalah tipe String
. Selanjutnya di artikel ini, kita akan melihat inisialisasi secara lebih detail dan mengeksplorasi bagaimana hal ini berhubungan dengan inisialisasi properti.
Meskipun properti gender
didefinisikan sebagai suatu konstantam masih mungkin mengubah nilainya selama inisialisasi suatu instance Person
. Beguu suatu instance diinisialisasi, properti gender
tidak bisa lagi dimodifikasi karena kita mendefinisikan properti tersebut sebagai properti konstanta dengan kata kunci let
. Selanjutnya ini akan menjadi lebih jelas di artikel ini ketika kita membahas tentang inisialisasi.
Metode
Kita bisa menambah perilaku atau fungsionalitas ke suatu kelas melalui fungsi atau metode. Di banyak bahasa pemrograman, istilah yang digunakan alih-alih fungsi dalam konteks kelas dan instance. Mendefinisikan metode hampir identik dengan mendefinisikan fungsi. Di contoh berikutnya, kita mendefinisikan metode fullName
di kelas Person
.
1 |
class Person { |
2 |
var firstName: String? |
3 |
var lastName: String? |
4 |
let gender = "female" |
5 |
|
6 |
func fullName() -> String { |
7 |
var parts: [String] = [] |
8 |
|
9 |
if let firstName = self.firstName { |
10 |
parts += [firstName] |
11 |
}
|
12 |
|
13 |
if let lastName = self.lastName { |
14 |
parts += [lastName] |
15 |
}
|
16 |
|
17 |
return " ".join(parts) |
18 |
}
|
19 |
}
|
Metode fullName
selanjutnya nested di definisi kelas. Metode ini tidak menerima parameter dan mengembalikan suatu String
. Implementasi metode fullName
cukup langsung ke tujuan. Melalui pengikatan opsional (optional binding), yang sudah kita bahas sebelumnya di seri ini, kita mengakses nilai yang disimpan dalam properti firstName
dan lastName
.
Kita menyimpan nama depan dan nama belakang instance Person
di suatu array dan menggabungkan bagian-bagiannya dengan suatu spasi. Alasan untuk implementasi yang canggung ini harus jelas, nama depan dan belakang boleh kosong, inilah mengapa kedua properti adalah tipe String?
.
Instansiasi
Kita telah mendefinisikan kelas dengan beberapa properti dan suatu metode. Bagaimana kita membuat suatu instance kelas
Person? Jika Anda akrab dengan Objective-C, Anda akan menyukai keringkasan snippet berikut.
1 |
let john = Person() |
Instansiasi suatu instance kelas sangat mirip dengan memanggil suatu fungsi. Untuk membuat suatu instance, nama kelas diikuti dengan sepasang tanda kurung, nilai yang dikembalikan lalu diberikan ke suatu konstanta atau variabel.
Di contoh kami, konstanta john
sekarang menunjuk ke suatu instance dari kelas Person
. Apakah itu berarti kita tidak bisa mengubah propertinya sama sekali? Contoh berikut menjawab pertanyaan ini.
1 |
john.firstName = "John" |
2 |
john.lastName = "Doe" |
3 |
john.gender = "male" |
Kita bisa mengakses properti suatu instance dengan menggunakan failitas dot syntax. Di contoh tersebut, kita mengatur firstName
ke "John"
, lastName
ke "Doe"
dan gender
ke "male"
. Sebelum kita membuat kesimpulan apapun berdasarkan contoh di atas, kita harus memeriksa kesalahan yang ada di tempat bermainnya.



Pengaturan firstName
dan lastName
kelihatannya tidak mengakibatkan permasalahan apapun. Menetapkan "male"
ke properti gender
bagaimanapun tetap akan menghasilkan kesalahan. Penjelasannya sederhana. Meskipun john
ditetapkan sebagai suatu konstanta, itu tidak akan mencegah modifikasi instance Person
. Namun ada satu kekurangan, hanya properti variable yang bisa dimodifikasi setelah inisialisasi suatu instance. Properti yang didefinisikan sebagai konstanta tidak bisa dimodifikasi setelah inisialisasi.
Perhatikan bahwa saya menekankan kata setelah di kalimat sebelumnya. Sebuah properti konstanta bisa dimodifikasi selama inisialisasi instance. Meskipun properti gender
tidak boleh diubah begitu instance Person
dibuat, kelasnya tidak akan banyak bermanfaat jika, misalnya, kita hanya bisa menginstansiasi instance Person
. Mari kita jadikan kelas Person
sedikit lebih fleksibel.
Inisialisasi
Inisialisasi adalah langkah sekali seumur hidup suatu instance kelas atau struktur. Selama inisialisasi, kami menyiapkan instance untuk digunakan dengan mengisi propertinya dengan nilai-nilai awal. Inisialisasi suatu instance bisa diswakreasi dengan mengimplementasikan suatu initializer, suatu metode tipe khusus. Mari menambahkan initializer ke kelas Person
.
1 |
class Person { |
2 |
var firstName: String? |
3 |
var lastName: String? |
4 |
let gender = "female" |
5 |
|
6 |
init() { |
7 |
gender = "male" |
8 |
}
|
9 |
}
|
Perhatikan bahwa initializernya, init
, tidak dimulai dengan kata kunci func
. Berlawanan dengan initializer di Objective-C, initializer di Swift tidak mengembalikan instance yang diinisialisasi.
Detail penting lainnya adalah cara mengatur properti gender
dengan nilai awal. Meskipun properti gender
didefinisikan sebagai properti konstanta, kita bisa mengatur nilainya di initializer. Kita mengatur properti gender
dengan menggunakan nama properti, tetapi bak juga untuk lebih eksplisit dan menuliskan kode berikut:
1 |
init() { |
2 |
self.gender = "male" |
3 |
}
|
Pada contoh di atas, self
merujuk pada contoh yang diinisialisasi. Ini berarti self.gender
merujuk pada properti gender
dari instance. Kita bisa mengabaikan self
, sebagaimana di contoh pertama, karena tidak ada kebingungan properti apa dimaksudkan. Meskipun tidak selalu seperti itu. Mari saya jelaskan apa maksudnya.
Parameter
Di banyak situasi, Anda mungkin ingin memasukkan nilai awal ke initializer untuk mengubahsuai instance yang Anda instansiasi. Ini dimungkinkan dengan membuat suatu initializer kustom yang menerima satu argumen atau lebih. Di contoh berikut kami membuat initializer kustom yang menerima satu argumen, gender
, dari tipe String
.
1 |
init(gender: String) { |
2 |
self.gender = gender |
3 |
}
|
Ada dua hal yang perlu diperhatikan. Pertama, kita harus mengakses properti gender
melalui self.gender
untuk menghindari ambiguitas karena nama parameter lokal setara dengan gender
. Yang kedua, meskipun kita belum menetapkan nama parameter eksternal, secara default Swift menciptakan nama parameter eksternal yang setara dengan nama parameter lokal. Hasilnya sama dengan seakan kita menambahkan simbol #
sebagai prefiks paramter gender
.
Di contoh berikut, kita menginstansiasi instance Person
dengan memanggil initializer kustom yang baru saja kita definisikan.
1 |
let bart = Person(gender: "male") |
2 |
|
3 |
println(bart.gender) // Outputs "male" |
Meskipun nilai awal properti gender
diset ke "female"
di definisi kelas, dengan memasukkan nilai dari parameter gender
kita bisa menetapkan nilai kustom ke konstanta properti gender
dalam proses inisialisasi.
Banyak Initializer
Seperti di Objective-C, suatu kelas atau struktur bisa memiliki banyak initializer. Di contoh berikut, kami membuat dua instance Person
. Di baris pertama, kami menggunakan initializer default. Di baris kedua, kami menggunakan initializer kustom yang kami definisikan sebelumnya.
1 |
let p1 = Person() |
2 |
let p2 = Person(gender: "male") |
4. Mendefinisikan suatu Struktur
Yang mengejutkan adalah bahwa struktur sangat mirip dengan kelas, tetapi berikut ada beberapa perbedaan kunci. Mari memulai dengan mendefinisikan suatu struktur dasar.
1 |
struct Wallet { |
2 |
var dollars: Int |
3 |
var cents: Int |
4 |
|
5 |
init() { |
6 |
dollars = 0 |
7 |
cents = 0 |
8 |
}
|
9 |
}
|
Sekilas satu-satunya perbedan adalah pada penggunaan kata kunci struct
, alih-alih class
. Contoh tersebut menunjukkan pada kita alternatif pendekatan untuk memasukkan nilai awal ke properti. Alih-alih mengeset nilai awal untuk tiap properti, kita bisa memberikan nilai awal properti dalam initializer struktur. Swift tidak akan melemparkan pesan kesalahan karena dia juga menginspeksi initializer untuk menentukan nilai awal—dan tipe—tiap properti.
5. Kelas dan Struktur
Anda mungkin mulai bertanya-tanya tentang perbedaan antara kelas dan struktur. Selayang pandang keduanya terlihat identik dalam bentuk dan fungsinya, dengan pengecualian kata kunci class
dan struct
. Kendatipun demikian ada sejumlah perbedaan utama.
Inheritance
Kelas mendukung inheritance, sedangkan struktur tidak. Contoh berikut mengilustrasikannya. Pola desain inheritance mutlak harus ada di pemrograman berorientasi objek dan di Swift inilah perbedaan utama antara kelas dan struktur.
1 |
class Person { |
2 |
var firstName: String? |
3 |
var lastName: String? |
4 |
let gender = "female" |
5 |
|
6 |
init(gender: String) { |
7 |
self.gender = gender |
8 |
}
|
9 |
}
|
10 |
|
11 |
class Student: Person { |
12 |
var school: String? |
13 |
}
|
14 |
|
15 |
let student = Student(gender: "male") |
Pada contoh di atas, kelas Person
adalah parent atau superclass dari kelas Student
. Ini berarti kelas Student
mewarisi properti dan perilaku kelas Person
. Baris terakhirnya mengilustrasikan ini. Kita menginisialisasi instance Student
dengan memanggil initializer custom yang kita definisikan sebelumnya di kelas Person
.
Menyalin dan Mereferensikan
Konsep berikut mungkin konsep Swift terpenting yang akan Anda pelajari hari ini, perbedaan antara tipe value dan reference. Struktur adalah tipe value, yang artinya tipe tersebut dilewati oleh suatu nilai. Suatu contoh mengilustrasikan hal tersebut dengan sangat baik.
1 |
struct Point { |
2 |
var x: Int |
3 |
var y: Int |
4 |
|
5 |
init(x: Int, y: Int) { |
6 |
self.x = x |
7 |
self.y = y |
8 |
}
|
9 |
}
|
10 |
|
11 |
var point1 = Point(x: 0, y: 0) |
12 |
var point2 = point1 |
13 |
|
14 |
point1.x = 10 |
15 |
|
16 |
println(point1.x) // Outputs 10 |
17 |
println(point2.x) // Outputs 0 |
Kita mendefinisikan struktur Point
untuk mengenkapsulasi data agar bisa menyimpan koordinat dalam ruang dua dimensi. Kita menginstansiasi point1
dengan x
setara 0
dan y
setara 0
. Kita tetapkan point1
ke point2
dan mengeset koordinat x
point1
ke 10
. Jika kita membuat keluaran koordinat x
kedua titik, kita akan menemukan bahwa keduanya tidak setara.
Struktur dilewati oleh nilai, sedangkan kelas oleh referensi. Jika Anda berencana untuk terus bekerja dengan Swift, Anda harus memahami pernyataan tersebut. Ketika kita menetapkan point1
ke point2
, Swift membuat salinan point1
dan menetapkannya ke point2
. Dengan kata lain, point1
dan point2
masing-masingnya menunjuk ke instance struktur Point
yang berbeda.
Sekarang mari mengulangi latihan ini dengan kelas Person
. Di contoh berikut, kita menginstansiasi instance Person
, mengeset propertinya, menetapkan person1
hingga person2
, dan memperbarui properti firstName
dari person1
. Untuk melihat referensi apa yang masuk untuk kelas, kita membuat keluaran nilai untuk properti firstName
untuk kedua instance Person
.
1 |
var person1 = Person(gender: "female") |
2 |
|
3 |
person1.firstName = "Jane" |
4 |
person1.lastName = "Doe" |
5 |
|
6 |
var person2 = person1 |
7 |
|
8 |
person1.firstName = "Janine" |
9 |
|
10 |
println(person1.firstName) |
11 |
println(person2.firstName) |
Contoh tersebut membuktikan bahwa kelas adalah tipe referensi. Ini berarti person1
dan person2
merujuk ke atau mereferensikan instance Person
yang sama. Dengan menetapkan person1
ke person2
, Swift tidak membuat salinan person1
. Variabel person2
menunjuk ke instance Person
yang sama dengan yang ditunjukkan oleh person1
. Mengubah properti firstName
person1
juga mempengaruhi properti firstName
person2
, karena keduanya mereferensikan instance Person
yang sama.
Sebagaimana saya sebutkan beberapa kali dalam artikel ini, kelas dan struktur sangatlah mirip. Yang memisahkan kelas dan struktur sangatlah penting. Jika konsep yang disampaikan di atas belum jelas, saya dorong Anda membaca artikelnya sekali lagi dan membiarkan konsep tersebut meresap ke dalam pikiran.
Pelajari Lebih Banyak di Kursus Pemrograman Swift Kami
Jika Anda tertarik lebih mendalami pembelajaran Swift, Anda bisa memeriksa kursus lengkap kami tentang pengembangan Swift.
Kesimpulan
Di serial Belajar Swift dari Nol ini, kita mulai mengeksplorasi dasar-dasar pemrograman berorientasi objek di Swift. Kelas dan struktur adalah blok bangunan fundamental kebanyakan proyek Swift dan kita akan mempelajarinya lebih lanjut di tutorial-tutorial berikutnya dalam seri ini.
Di artikel berikutnya, kita akan melanjutkan eksplorasi kelas dan struktur dengan melihat lebih dekat pada properti dan inheritance.