Saya mencoba untuk secara dinamis membuat class
tipe berbasis contoh menggunakan obat generik, namun saya mengalami kesulitan dengan introspeksi kelas.
Inilah pertanyaannya:
- Apakah ada Swift yang setara dengan Obj-C
self.class
? - Apakah ada cara untuk membuat instance kelas menggunakan
AnyClass
hasil dariNSClassFromString
? - Apakah ada cara untuk mendapatkan
AnyClass
atau mengetik informasi secara ketat dari parameter generikT
? (Mirip dengantypeof(T)
sintaks C # )
introspection
swift
Erik
sumber
sumber
self.class
akan menjadiself.dynamicType.self
dalam keyakinan Swift Iself.dynamicType.foo()
Jawaban:
Yah, untuk satu, padanan Swift
[NSString class]
adalah.self
(lihat dokumen Metatype , meskipun mereka cukup tipis).Bahkan,
NSString.class
tidak berhasil! Anda harus menggunakanNSString.self
.Begitu pula dengan kelas yang sigap saya coba ...
Hmm… kesalahannya mengatakan:
Butuh beberapa saat bagi saya untuk memikirkan apa artinya ini… ternyata kelas itu ingin memiliki a
@required init()
Beberapa dokumen menyebut ini sebagai
.Type
, tetapiMyClass.Type
memberi saya kesalahan di taman bermain.sumber
.Type
atau.Protocol
dalam deklarasi variabel, misalnyalet myObject: MyObject.Type = MyObject.self
@
sebelumrequired
harus dihapusBerikut cara menggunakannya
NSClassFromString
. Anda harus mengetahui superclass tentang apa yang akan Anda hasilkan. Berikut adalah pasangan superclass-subclass yang tahu bagaimana mendeskripsikan diri mereka sendiriprintln
:Perhatikan penggunaan
@obj
sintaks khusus untuk mendikte nama Objective-C munged dari kelas-kelas ini; itu penting, karena jika tidak kita tidak tahu string munged yang menunjukkan setiap kelas.Sekarang kita bisa gunakan
NSClassFromString
untuk membuat kelas Zork atau kelas Zilk, karena kita tahu kita bisa mengetiknya sebagai NSObject dan tidak crash nanti:Dan itu bisa dibalik;
println(NSStringFromClass(anObject.dynamicType))
juga bekerja.Versi modern:
sumber
@objc(ClassName)
bit tersebut. Saya tahu tentang@objc
atributnya tetapi tidak Anda juga bisa memberikan petunjuk tentang nama kelas.as! NSObject.Type
di baris pertama danaClass.init()
yang keduaJika saya membaca dokumentasi dengan benar, jika Anda berurusan dengan instance dan misalnya ingin mengembalikan instance baru dari Type yang sama daripada objek yang telah Anda berikan dan Type dapat dibangun dengan init () Anda dapat melakukan:
Saya segera mengujinya dengan String:
yang bekerja dengan baik.
sumber
dynamicType
bekerja seperti yang saya harapkan di sana. Namun, saya tidak dapat membandingkan tipe. Penggunaan yang sangat besar adalah dengan obat generik, jadi saya bisa memiliki sesuatu sepertiGeneric<T>
dan di dalamnyaif T is Double {...}
. Tampaknya hal itu tidak mungkin terjadi.Defaultable
protokol yang bekerja mirip dengandefault
kata kunci C # , dan ekstensi yang sesuai untuk jenis sepertiString
danInt
. Dengan menambahkan batasan umum dariT:Defaultable
, saya dapat memeriksa apakah argumen tersebut berhasilis T.default()
.value is String.default()
... dll, yang akhirnya akan Anda lakukanvalue is String
.Dalam 3 cepat
sudah ditinggalkan.
Sebagai gantinya gunakan:
sumber
Implementasi cepat untuk membandingkan tipe
CATATAN: Perhatikan bahwa itu juga bekerja dengan protokol objek mungkin atau mungkin tidak diperluas
sumber
Akhirnya ada sesuatu untuk dikerjakan. Agak malas tetapi bahkan rute NSClassFromString () tidak berfungsi untuk saya ...
dan bingo, "makeFoo" berisi instance Foo.
Kelemahannya adalah kelas Anda harus keluar dari FactoryObject dan mereka HARUS memiliki metode inisialisasi Obj-C + sehingga kelas Anda secara otomatis dimasukkan ke dalam peta kelas dengan fungsi global "mapClass".
sumber
Berikut adalah contoh lain yang menunjukkan implementasi hierarki kelas, mirip dengan jawaban yang diterima, diperbarui untuk rilis pertama Swift.
Cetak hasil ini:
sumber
var x: NamedItem.Type
, jika saya menetapkannyax = Folder.Type
, makax()
mengembalikan baruNamedItem
, bukanFolder
. Ini membuat teknik tidak berguna untuk banyak aplikasi. Saya menganggap ini bug .