Dentang menambahkan kata kunci instancetype
yang, sejauh yang saya bisa lihat, menggantikan id
sebagai jenis kembali -alloc
dan init
.
Apakah ada manfaat menggunakan instancetype
bukan id
?
objective-c
instancetype
griotspeak
sumber
sumber
id
telah digantiinstancetype
, bahkaninit
dariNSObject
. Jika Anda ingin membuat kode Anda kompatibel dengan swift, Anda harus menggunakaninstancetype
Jawaban:
Pasti ada manfaatnya. Saat Anda menggunakan 'id', pada dasarnya Anda tidak mendapatkan pengecekan tipe sama sekali. Dengan instancetype, kompiler dan IDE tahu apa jenis yang dikembalikan, dan dapat memeriksa kode Anda lebih baik dan autocomplete lebih baik.
Hanya gunakan di tempat yang masuk akal saja (yaitu metode yang mengembalikan instance kelas itu); id masih berguna.
sumber
alloc
,,init
dll. secara otomatis dipromosikaninstancetype
oleh kompiler. Itu tidak berarti tidak ada manfaatnya; memang ada, tapi bukan ini.Ya, ada manfaat menggunakan
instancetype
dalam semua kasus yang berlaku. Saya akan menjelaskan lebih detail, tetapi saya akan mulai dengan pernyataan tebal ini: Gunakaninstancetype
kapan saja sesuai, yang mana setiap kali kelas mengembalikan instance dari kelas yang sama.Faktanya, inilah yang dikatakan Apple tentang masalah ini:
Dengan itu, mari kita lanjutkan dan jelaskan mengapa itu ide yang bagus.
Pertama, beberapa definisi:
Untuk pabrik kelas, Anda harus selalu menggunakannya
instancetype
. Kompiler tidak secara otomatis dikonversiid
keinstancetype
. Ituid
adalah objek generik. Tetapi jika Anda menjadikannyainstancetype
kompiler tahu jenis objek apa metode kembali.Ini bukan masalah akademis. Misalnya,
[[NSFileHandle fileHandleWithStandardOutput] writeData:formattedData]
akan menghasilkan kesalahan pada Mac OS X ( hanya ) Beberapa metode bernama 'writeData:' ditemukan dengan hasil yang tidak cocok, tipe parameter atau atribut . Alasannya adalah bahwa NSFileHandle dan NSURLHandle menyediakan awriteData:
. Sejak[NSFileHandle fileHandleWithStandardOutput]
mengembalikan sebuahid
, kompiler tidak yakin kelas apawriteData:
yang dipanggil.Anda perlu mengatasinya, menggunakan:
atau:
Tentu saja, solusi yang lebih baik adalah mendeklarasikan
fileHandleWithStandardOutput
sebagai mengembalikan suatuinstancetype
. Maka para pemeran atau tugas tidak perlu.(Perhatikan bahwa pada iOS, contoh ini tidak akan menghasilkan kesalahan karena hanya
NSFileHandle
menyediakan kesalahan diwriteData:
sana. Contoh lain ada, sepertilength
, yang mengembalikan aCGFloat
dariUILayoutSupport
tetapi aNSUInteger
dariNSString
.)Catatan : Sejak saya menulis ini, header macOS telah dimodifikasi untuk mengembalikan
NSFileHandle
bukanid
.Untuk inisialisasi, ini lebih rumit. Saat Anda mengetik ini:
... kompiler akan berpura-pura Anda mengetik ini sebagai gantinya:
Ini diperlukan untuk ARC. Ini dijelaskan dalam tipe hasil Terkait Ekstensi Bahasa Dentang . Inilah sebabnya mengapa orang akan mengatakan kepada Anda bahwa itu tidak perlu digunakan
instancetype
, meskipun saya berpendapat Anda harus menggunakannya. Sisa dari jawaban ini berkaitan dengan ini.Ada tiga keuntungan:
Eksplisit
Memang benar bahwa tidak ada manfaat teknis untuk kembali
instancetype
dariinit
. Tetapi ini karena kompiler secara otomatis mengonversiid
keinstancetype
. Anda mengandalkan kekhasan ini; saat Anda menulis bahwainit
mengembalikan sebuahid
, kompiler menafsirkannya seolah-olah mengembalikan sebuahinstancetype
.Ini sama dengan kompiler:
Ini tidak setara dengan mata Anda. Paling-paling, Anda akan belajar untuk mengabaikan perbedaan dan membaca sepintas lalu. Ini bukan sesuatu yang harus Anda pelajari untuk diabaikan.
Pola
Meskipun tidak ada perbedaan dengan
init
dan metode lain, ada adalah perbedaan segera setelah Anda mendefinisikan sebuah pabrik kelas.Keduanya tidak setara:
Anda menginginkan bentuk kedua. Jika Anda terbiasa mengetik
instancetype
sebagai tipe pengembalian konstruktor, Anda akan melakukannya dengan benar setiap waktu.Konsistensi
Akhirnya, bayangkan jika Anda menggabungkan semuanya: Anda menginginkan
init
fungsi dan juga pabrik kelas.Jika Anda menggunakan
id
untukinit
, Anda berakhir dengan kode seperti ini:Tetapi jika Anda menggunakan
instancetype
, Anda mendapatkan ini:Ini lebih konsisten dan lebih mudah dibaca. Mereka mengembalikan hal yang sama, dan sekarang sudah jelas.
Kesimpulan
Kecuali Anda sengaja menulis kode untuk kompiler lama, Anda harus menggunakannya
instancetype
saat yang tepat.Anda harus ragu sebelum menulis pesan yang mengembalikan
id
. Tanyakan kepada diri sendiri: Apakah ini mengembalikan instance kelas ini? Jika demikian, ini adalahinstancetype
.Tentu saja ada kasus di mana Anda harus kembali
id
, tetapi Anda mungkin akan menggunakaninstancetype
lebih sering.sumber
instancetype
vsid
benar-benar bukan keputusan gaya. Perubahan terbaru sekitarinstancetype
benar - benar membuat jelas bahwa kita harus menggunakaninstancetype
di tempat-tempat seperti di-init
mana kita maksudkan 'instance dari kelas saya'Jawaban di atas lebih dari cukup untuk menjelaskan pertanyaan ini. Saya hanya ingin menambahkan contoh bagi pembaca untuk memahaminya dalam hal pengkodean.
Kelas A
Kelas B
TestViewController.m
sumber
Anda juga bisa mendapatkan detail di The Designated Initializer
**
INSTANCETYPE
** Kata kunci ini hanya dapat digunakan untuk jenis kembali, yang cocok dengan jenis penerima kembali. Metode init selalu dinyatakan untuk mengembalikan tipe instancet. Mengapa tidak membuat Pesta jenis pengembalian untuk pesta misalnya, misalnya? Itu akan menimbulkan masalah jika kelas Partai pernah subkelas. Subclass akan mewarisi semua metode dari Party, termasuk initializer dan tipe pengembaliannya. Jika turunan dari subclass dikirimi pesan penginisialisasi ini, apakah itu akan dikembalikan? Bukan pointer ke instance Party, tapi pointer ke instance dari subclass. Anda mungkin berpikir itu Tidak masalah, saya akan mengganti initializer di subclass untuk mengubah tipe return. Tetapi dalam Objective-C, Anda tidak dapat memiliki dua metode dengan pemilih yang sama dan jenis pengembalian yang berbeda (atau argumen). Dengan menetapkan bahwa metode inisialisasi kembali "
Indo
** Sebelum instancetype diperkenalkan di Objective-C, initializers mengembalikan id (eye-dee). Tipe ini didefinisikan sebagai "penunjuk ke objek apa pun". (id sangat mirip void * dalam C.) Pada tulisan ini, templat kelas XCode masih menggunakan id sebagai jenis pengembalian inisialisasi yang ditambahkan dalam kode boilerplate. Tidak seperti tipe instancetype, id dapat digunakan lebih dari sekedar tipe pengembalian. Anda bisa mendeklarasikan variabel atau parameter metode id tipe ketika Anda tidak yakin jenis objek apa yang akan ditunjukkan oleh variabel. Anda dapat menggunakan id saat menggunakan enumerasi cepat untuk beralih di atas larik objek yang banyak atau tidak diketahui. Perhatikan bahwa karena id tidak didefinisikan sebagai "penunjuk ke objek apa pun," Anda tidak menyertakan * ketika mendeklarasikan variabel atau parameter objek jenis ini.
sumber