Generik dan Parameter Tipe
Pahami cara menulis kelas dan metode generik untuk membuat komponen yang dapat digunakan kembali dengan keamanan tipe.
Generik dan Parameter Tipe adalah pelajaran Scala for Backend Engineering & Functional Programming gratis di CoddyKit. Ini adalah pelajaran 1 dari 3. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Scala for Backend Engineering & Functional Programming, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Scala for Backend Engineering & Functional Programming mencakup 3 pelajaran total.
Apa Itu Generik?
Bayangkan Anda perlu membuat wadah yang dapat menampung item dengan tipe apa pun, seperti String, Int, atau objek khusus. Tanpa generik, Anda harus menulis wadah terpisah untuk setiap tipe sehingga kode menjadi berulang, atau menggunakan tipe yang sangat umum seperti Any.
Generik memungkinkan Anda menulis kode yang fleksibel dan dapat digunakan kembali untuk berbagai tipe data, sekaligus tetap memberikan keamanan tipe saat kompilasi. Ini seperti cetak biru yang nantinya dapat diisi dengan bahan yang berbeda!
Perangkap Tipe `Any`
Menggunakan Any sebagai pengganti tipe dapat menimbulkan masalah. Meskipun Anda dapat menyimpan apa pun, informasi tipe spesifiknya akan hilang. Akibatnya, Anda sering perlu melakukan konversi tipe pada item agar kembali ke tipe aslinya. Cara ini rentan terhadap kesalahan dan dapat menyebabkan program mengalami kerusakan saat dijalankan jika konversinya tidak benar.
Cobalah menjalankan contoh ini dan pikirkan potensi masalahnya:
class ItemHolder(val item: Any)
object Main {
def main(args: Array[String]): Unit = {
val stringHolder = new ItemHolder("Hello Scala")
val numberHolder = new ItemHolder(123)
// We need to cast, and it's unsafe if we get it wrong
val retrievedString = stringHolder.item.asInstanceOf[String]
println(s"Retrieved String: $retrievedString")
// If we uncomment the line below, it compiles but will crash at runtime!
// val wrongType = numberHolder.item.asInstanceOf[String]
// println(s"Wrong Type: $wrongType")
}
}Memperkenalkan Parameter Tipe
Generik mengatasi perangkap tipe Any dengan memperkenalkan parameter tipe. Parameter ini berfungsi seperti pengganti untuk tipe sebenarnya yang Anda tentukan saat membuat instans kelas atau memanggil metode.
Di Scala, parameter tipe ditulis menggunakan kurung siku ([]) setelah nama kelas atau metode, biasanya menggunakan satu huruf kapital seperti T, A, B, dan seterusnya. Sebagai contoh, class Box[T] mendeklarasikan kelas generik Box yang menerima satu parameter tipe T.
Membangun Box Generik
Mari kita membuat kelas generik sederhana bernama Box yang dapat menampung konten dengan tipe apa pun. Perhatikan bahwa T digunakan di seluruh definisi kelas untuk mewakili tipe konten.
Dengan begitu, kita dapat membuat kotak untuk string, bilangan bulat, atau tipe lainnya tanpa menulis kelas terpisah untuk masing-masing tipe.
class Box[T](val content: T) {
def get: T = content
override def toString: String = s"Box($content)"
}
object Main {
def main(args: Array[String]): Unit = {
val stringBox = new Box("Scala is fun!")
val intBox = new Box(42)
val booleanBox = new Box(true)
println(stringBox)
println(intBox)
println(booleanBox)
}
}Keamanan Tipe dengan Generik
Keunggulan terbesar generik adalah keamanan tipe saat kompilasi. Saat Anda membuat Box[String], kompiler mengetahui bahwa kotak tersebut hanya boleh berisi string. Jika Anda mencoba memasukkan bilangan bulat ke dalamnya atau mengambil isinya sebagai bilangan bulat, kompiler akan segera mendeteksi kesalahan tersebut.
Hal ini mencegah banyak kesalahan umum saat program berjalan yang dapat terjadi pada pendekatan yang kurang aman terhadap tipe, seperti penggunaan Any.
class Box[T](val content: T) {
def get: T = content
}
object Main {
def main(args: Array[String]): Unit = {
val myStringBox: Box[String] = new Box("CoddyKit")
val myIntBox: Box[Int] = new Box(100)
// This works, type is String
val s: String = myStringBox.get
println(s"String from box: $s")
// This works, type is Int
val i: Int = myIntBox.get
println(s"Int from box: $i")
// The compiler prevents this line from compiling:
// val wrong: String = myIntBox.get // Type mismatch error!
}
}Metode Juga Bisa Generik!
Sama seperti kelas, metode individual juga dapat bersifat generik. Metode generik dapat menerima parameter tipe yang hanya berlaku di dalam metode tersebut, sehingga metode itu dapat bekerja dengan berbagai tipe tanpa mengharuskan seluruh kelas menjadi generik.
Ini berguna ketika Anda memiliki operasi tertentu yang dapat diterapkan pada berbagai tipe, tetapi kelasnya sendiri bukan wadah generik.
Metode `printPair` yang Fleksibel
Berikut contoh metode generik printPair. Metode ini menerima dua parameter tipe, A dan B, sehingga dapat mencetak pasangan yang terdiri dari dua tipe apa pun. Perhatikan bahwa parameter tipe dideklarasikan tepat setelah nama metode.
Dengan demikian, metode ini dapat digunakan kembali untuk berbagai kombinasi data.
object Util {
def printPair[A, B](first: A, second: B): Unit = {
println(s"Pair: ($first, $second)")
println(s"Type of first: ${first.getClass.getName}")
println(s"Type of second: ${second.getClass.getName}")
}
}
object Main {
def main(args: Array[String]): Unit = {
Util.printPair("Hello", 123)
Util.printPair(true, List(1, 2, 3))
Util.printPair(4.5, 'C')
}
}Inferensi Tipe yang Cerdas
Salah satu fitur Scala yang kuat adalah inferensi tipe. Saat menggunakan kelas atau metode generik, Anda sering kali tidak perlu menentukan parameter tipe secara eksplisit. Kompiler Scala cukup cerdas untuk menentukannya berdasarkan argumen yang Anda berikan.
Hal ini membuat kode Anda lebih ringkas dan mudah dibaca tanpa mengorbankan keamanan tipe.
class Container[T](val item: T) {
def getItem: T = item
}
object Main {
def main(args: Array[String]): Unit = {
// Scala infers T as String
val stringContainer = new Container("Inferred String")
println(s"Content: ${stringContainer.getItem}, Type: ${stringContainer.getItem.getClass.getName}")
// Scala infers T as Double
val doubleContainer = new Container(3.14)
println(s"Content: ${doubleContainer.getItem}, Type: ${doubleContainer.getItem.getClass.getName}")
// You can also specify explicitly, but often not needed
val explicitIntContainer: Container[Int] = new Container(500)
println(s"Content: ${explicitIntContainer.getItem}, Type: ${explicitIntContainer.getItem.getClass.getName}")
}
}Membatasi Tipe Generik dengan Batasan
Terkadang, Anda ingin kelas atau metode generik hanya bekerja dengan tipe yang memiliki kemampuan tertentu. Misalnya, metode yang menjumlahkan angka seharusnya hanya menerima tipe numerik.
Batasan tipe memungkinkan Anda membatasi tipe yang dapat digunakan sebagai parameter tipe. Batas atas (<:) berarti parameter tipe harus merupakan subtipe dari tipe tertentu. Sebagai contoh, [T <: Animal] berarti T harus berupa Animal atau subtipe dari Animal.
class Animal { def speak(): String = "..." }
class Dog extends Animal { override def speak(): String = "Woof!" }
class Cat extends Animal { override def speak(): String = "Meow!" }
// This box can only hold types that are Animal or its subtypes
class AnimalShelter[T <: Animal](val animal: T) {
def getAnimalSound: String = animal.speak()
}
object Main {
def main(args: Array[String]): Unit = {
val dogShelter = new AnimalShelter(new Dog())
println(s"Dog says: ${dogShelter.getAnimalSound}")
val catShelter = new AnimalShelter(new Cat())
println(s"Cat says: ${catShelter.getAnimalSound}")
// This would NOT compile because Car is not an Animal:
// class Car
// val carShelter = new AnimalShelter(new Car())
}
}Tantangan Kelas Generik
Saatnya menguji pemahaman Anda tentang generik!
Baca pernyataan berikut dengan saksama, lalu pilih semua pernyataan yang benar tentang kelas dan metode generik di Scala.
Generik: Hal-Hal Penting
Dalam pelajaran ini, kita telah mempelajari generik di Scala, yaitu fitur yang kuat untuk menulis kode yang fleksibel dan aman terhadap tipe.
- Generik memungkinkan kelas dan metode bekerja dengan berbagai tipe.
- Generik menggunakan parameter tipe (misalnya,
[T]) sebagai pengganti untuk tipe sebenarnya. - Generik menyediakan keamanan tipe saat kompilasi sehingga mencegah kesalahan saat program berjalan.
- Inferensi tipe Scala sering kali membuat kode generik menjadi ringkas.
- Batasan tipe (misalnya,
<:) dapat membatasi parameter tipe ke subtipe tertentu.
Dengan menggunakan generik, Anda dapat menulis komponen yang dapat digunakan kembali, tangguh, dan mudah disesuaikan dengan berbagai tipe data. Dengan demikian, kode Scala Anda menjadi lebih kuat dan tidak mudah mengalami kesalahan.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Generik dan Parameter Tipe” gratis?
Ya — teks lengkap “Generik dan Parameter Tipe” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Scala for Backend Engineering & Functional Programming, upgrade ke CoddyKit PRO. Kursus Scala for Backend Engineering & Functional Programming mencakup 3 pelajaran total.
Apa yang akan aku pelajari di “Generik dan Parameter Tipe”?
Pahami cara menulis kelas dan metode generik untuk membuat komponen yang dapat digunakan kembali dengan keamanan tipe. Kamu berlatih Scala for Backend Engineering & Functional Programming dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Scala for Backend Engineering & Functional Programming?
Tidak diperlukan pengalaman sebelumnya. Scala for Backend Engineering & Functional Programming di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 1 dari 3.
Berapa lama pelajaran “Generik dan Parameter Tipe” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Scala for Backend Engineering & Functional Programming ini?
Ya. Setiap pelajaran Scala for Backend Engineering & Functional Programming menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Generik dan Parameter Tipe
- Varians: Kovarians & Kontravarians
- Kelas Tipe dan Implisit