Opaque Type (tipe buram) — adalah mekanisme Swift yang memungkinkan fungsi mengembalikan nilai dari suatu tipe tanpa mengungkapkan tipe konkret ke kode pemanggil. Kata kunci some dalam tipe kembalian — contoh paling terkenal: some View di SwiftUI berarti "dikembalikan suatu tipe yang sesuai dengan View, tetapi yang mana persisnya — detail implementasi". Opaque type mempertahankan identitas tipe (berbeda dengan protokol sebagai tipe), yang memungkinkan kompiler mengoptimalkan kode dan menjamin konsistensi tipe kembalian. Menurut Swift Book, 2025, opaque types memecahkan masalah protokol dengan associated types, memungkinkan pengembalian nilai protokol tersebut dari fungsi.
Poin Utama
Opaque Type — adalah tipe kembalian, dideklarasikan dengan kata kunci some, yang menyembunyikan implementasi konkret dari kode pemanggil. Pihak pemanggil hanya tahu bahwa nilai kembalian sesuai dengan protokol tertentu, tetapi tidak tahu tipe konkret apa yang ada di belakang some. Pada saat yang sama, kompiler mengetahui tipe pastinya dan menggunakannya untuk dispatch statis dan optimalisasi.
Sebelum kemunculan opaque types di Swift 5.1 (SE-0244), tidak mungkin mengembalikan protokol dengan associated types dari fungsi tanpa pembungkus boxing. Misalnya, protokol Equatable memiliki associated type dan fungsi tidak bisa begitu saja mengembalikan Equatable — kompiler memberikan kesalahan "protocol can only be used as a generic constraint". Opaque type memecahkan masalah ini.
func makeInt() -> some Equatable {
return 42
}
func makeString() -> some Equatable {
return "Hello"
}
// Kompiler tahu makeInt mengembalikan Int
// makeInt() == makeString() — ❌ kesalahan, tipe berbeda
Kedua fungsi mengembalikan some Equatable, tetapi tipe konkret berbeda: Int dan String. Upaya membandingkannya dengan == akan menyebabkan kesalahan kompilasi, karena opaque type menjamin bahwa dari panggilan konkret dikembalikan tipe yang sama, tetapi tidak antara fungsi yang berbeda. Ini adalah fitur, bukan bug: opaque type mempertahankan identitas tipe di mana protokol sebagai tipe (any Equatable) kehilangannya.
Generic dan Opaque Type — dua sisi dari koin yang sama. Generic memungkinkan kode pemanggil memilih tipe, sedangkan opaque type memungkinkan fungsi menyembunyikan tipe dari kode pemanggil. Perbedaannya ada pada arah kontrol.
| Karakteristik | Generic | Opaque some |
|---|---|---|
| Siapa yang memilih tipe | Kode pemanggil | Fungsi/metode |
| Identitas tipe | Dipertahankan (stabil) | Dipertahankan (stabil) |
| Jumlah cabang return | Satu (melalui generic) | Tipe yang sama di semua cabang |
| Penerapan | Algoritma, struktur data | SwiftUI, metode pabrik |
Dalam fungsi generic, caller memutuskan tipe apa yang akan digunakan. Fungsi harus bekerja dengan T apa pun yang memenuhi batasan. Untuk opaque type, caller tidak tahu tipe konkret — keputusan diambil oleh implementasi.
// Generic: caller memilih tipe
func identity<T>(_ value: T) -> T { value }
let x: Int = identity(42)
// Opaque: fungsi menyembunyikan tipe
func makeSomeEquatable() -> some Equatable { 42 }
let y = makeSomeEquatable()
Pilihan antara generic dan opaque type tergantung pada niat. Jika kode pemanggil harus memilih tipe — gunakan generic. Jika fungsi harus menyembunyikan detail implementasi — gunakan some. SwiftUI memilih some View justru karena body harus fleksibel di dalam tetapi stabil di luar.
some — adalah kata kunci Swift, diperkenalkan di Swift 5.1 (SE-0244). Digunakan di posisi kembalian untuk mendeklarasikan opaque type, serta di parameter (SE-0341) dan properti. some menjamin bahwa tipe konkret stabil dan diketahui kompiler, tetapi tersembunyi dari kode eksternal.
Mulai Swift 5.7, some dapat digunakan tidak hanya di posisi kembalian, tetapi juga di parameter. some Equatable di parameter berarti "fungsi ini menerima tipe Equatable apa pun, tetapi semua panggilan di dalam body konkret melihat tipe yang sama".
func areEqual(_ a: some Equatable, _ b: some Equatable) -> Bool {
// a dan b — berpotensi tipe berbeda, == tidak akan bekerja langsung
return isEqual(a, b)
}
func isEqual<T: Equatable>(_ a: T, _ b: T) -> Bool {
return a == b
}
Penggunaan some di parameter memberikan sintaks yang lebih ringkas dibandingkan
any — adalah kata kunci Swift 5.6+ untuk deklarasi eksplisit tipe eksistensial (protokol sebagai tipe). Berbeda dengan some, any menghapus identitas tipe: kompiler tidak tahu tipe konkret apa yang tersembunyi di balik protokol. Ini memberikan fleksibilitas (berbagai tipe dapat disimpan dalam satu array), tetapi dengan mengorbankan performa.
some — polimorfisme statis: kompiler mengetahui tipe konkret, menggunakan dispatch langsung dan dapat melakukan inline kode. any — polimorfisme dinamis: menggunakan tabel metode virtual (existential container), yang menambah ketidaklangsungan.
protocol Drawable {
func draw()
}
// some: tipe statis diketahui
func makeDrawable() -> some Drawable {
return Circle() // Tipe kembalian tunggal
}
// any: dinamis, dapat menyimpan tipe berbeda
var shapes: [any Drawable] = [Circle(), Square()]
shapes.append(Triangle())
Pilihan antara some dan any adalah kompromi antara performa dan fleksibilitas. Some lebih cepat, tetapi membatasi pada satu implementasi. Any lebih fleksibel (tipe dapat dicampur), tetapi lebih lambat karena dispatch dinamis. Di SwiftUI, untuk body selalu digunakan some View, karena body setiap View adalah satu tipe konkret.
Opaque Type memecahkan masalah fundamental Swift: protokol dengan associated types (PAT) tidak dapat digunakan langsung sebagai tipe. Fungsi tidak bisa begitu saja mengembalikan Collection — kompiler memerlukan spesifikasi Element. some Collection menyelesaikan ini dengan menyembunyikan associated type.
Tanpa opaque type, untuk mengembalikan Collection harus menggunakan tipe konkret (Array
func makeReversedCollection<T>(
of array: [T]
) -> some Collection {
return array.reversed()
}
let result = makeReversedCollection(of: [1, 2, 3])
// result — ReversedCollection>, hidden from caller
for item in result {
print(item)
}
result dapat diiterasi, tetapi properti ReversedCollection tidak dapat langsung diakses. Ini melindungi enkapsulasi: jika kemudian reversed() diganti dengan metode lain dengan implementasi berbeda, kode pemanggil tidak akan rusak. Opaque type memberikan kebebasan mengubah implementasi tanpa mengubah API.
some View — penerapan opaque type yang paling terkenal. Setiap View di SwiftUI mendeklarasikan body sebagai some View. Ini berarti body mengembalikan suatu tipe View konkret, tetapi programmer tidak perlu memikirkan apa sebenarnya — TupleView, Group, ModifiedContent atau tipe lain dari framework.
Tanpa opaque type, body harus mengembalikan tipe konkret, misalnya ModifiedContent<Button<Text>, Padding>, yang tidak praktis. some View menyembunyikan kompleksitas ini. Kompiler menyimpulkan tipe pasti body secara otomatis saat kompilasi.
struct ContentView: View {
var body: some View {
VStack {
Text("Halo")
.font(.title)
Button("Sentuh aku") {
print("Tersentuh")
}
}
.padding()
}
}
Kompiler menyimpulkan body sebagai ModifiedContent<VStack<TupleView<(Text, Button<Text>)>>, Padding>. Programmer melihat some View. Jika layout berubah dari VStack ke HStack, kompiler secara otomatis menyimpulkan ulang tipe — tanpa pengeditan manual. Inilah keajaiban opaque type: programmer fokus pada logika antarmuka, bukan pada tipe komposisi.
Pertanyaan yang Sering Diajukan
Opaque Type — adalah tipe yang dideklarasikan dengan kata kunci some, yang menyembunyikan implementasi konkret dari kode pemanggil. Kompiler mengetahui tipe pastinya, tetapi programmer yang menggunakan fungsi hanya melihat protokol.
some — adalah opaque type dengan identitas statis: kompiler mengetahui tipe konkret. any — adalah tipe eksistensial dengan dispatch dinamis: identitas tipe dihapus. Some lebih efisien, any lebih fleksibel.
some View menyembunyikan tipe konkret kompleks body yang disimpulkan kompiler secara otomatis. Ini membebaskan programmer dari kebutuhan menulis tipe pasti yang terdiri dari pembungkus Generic (VStack, Group, ModifiedContent).
Ya, mulai Swift 5.7. some di parameter adalah gula sintaksis di atas parameter generic. Ini menyederhanakan deklarasi fungsi, terutama saat bekerja dengan protokol, di mana setiap some-parameter tidak memerlukan
Kompiler akan memberikan kesalahan: opaque type mengharuskan semua cabang return mengembalikan tipe konkret yang sama. Ini sengaja dilakukan untuk mempertahankan identitas tipe. Jika perlu mengembalikan tipe berbeda, gunakan any.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga