Próbuję dynamicznie tworzyć class
typy oparte na instancjach przy użyciu typów ogólnych, jednak napotykam trudności z introspekcją klas.
Oto pytania:
- Czy istnieje odpowiednik języka Swift dla Obj-C
self.class
? - Czy istnieje sposób na utworzenie wystąpienia klasy przy użyciu
AnyClass
wyniku zNSClassFromString
? - Czy istnieje sposób, aby uzyskać
AnyClass
lub w inny sposób wpisać informacje wyłącznie z parametru ogólnegoT
? (Podobna dotypeof(T)
składni C # )
introspection
swift
Erik
źródło
źródło
self.class
stałyby sięself.dynamicType.self
w Swift Iself.dynamicType.foo()
Odpowiedzi:
Cóż, po pierwsze, Swift odpowiednikiem
[NSString class]
jest.self
(zobacz dokumentację Metatype , chociaż są dość cienkie).W rzeczywistości
NSString.class
nawet nie działa! Musisz użyćNSString.self
.Podobnie z szybką klasą próbowałem ...
Hmm… błąd mówi:
Zajęło mi trochę czasu, zanim zrozumiałem, co to znaczy… okazuje się, że chce, aby klasa miała
@required init()
Niektóre dokumenty odnoszą się do tego jako
.Type
, ale wyświetlaMyClass.Type
mi błąd na placu zabaw.źródło
.Type
lub.Protocol
w deklaracji zmiennej, np.let myObject: MyObject.Type = MyObject.self
@
wcześniejrequired
należy usunąćOto jak używać
NSClassFromString
. Musisz znać superklasę tego, z czym skończysz. Oto para nadklasa-podklasa, która wie, jak się opisać dlaprintln
:Zwróć uwagę na użycie specjalnej
@obj
składni, która dyktuje nazwę tych klas zmienioną przez Objective-C; jest to kluczowe, ponieważ w przeciwnym razie nie znamy połączonego łańcucha, który wyznacza każdą klasę.Teraz możemy użyć
NSClassFromString
do stworzenia klasy Zork lub Zilk, ponieważ wiemy, że możemy wpisać go jako obiekt NSO i nie ulegnie awarii później:I to jest odwracalne;
println(NSStringFromClass(anObject.dynamicType))
również działa.Nowoczesna wersja:
źródło
@objc(ClassName)
trochę. Wiedziałem o@objc
atrybucie, ale nie wiedziałem, że możesz też podać wskazówkę dotyczącą nazwy klasy.as! NSObject.Type
w pierwszej linii iwaClass.init()
drugiejJeśli dobrze czytam dokumentację, jeśli masz do czynienia z instancjami i np. Chcesz zwrócić nową instancję tego samego typu niż obiekt, który otrzymałeś, a Type można skonstruować za pomocą init (), możesz zrobić:
Szybko przetestowałem to ze Stringiem:
który działał dobrze.
źródło
dynamicType
działa tak , jak się spodziewałem. Jednak nie udało mi się porównać typów. Naprawdę duże zastosowanie ma generyczne, więc mógłbym mieć coś podobnegoGeneric<T>
i wewnątrzif T is Double {...}
. Wydaje się, że nie jest to możliwe niestety.Defaultable
protokół, który działa podobnie dodefault
słowa kluczowego C # i odpowiednie rozszerzenia dla typów takich jakString
iInt
. Dodając ogólne ograniczenieT:Defaultable
, mogłem sprawdzić, czy argument został przekazanyis T.default()
.value is String.default()
... itd., co po prostu skończyłbyśvalue is String
zamiast tego.W swift 3
jest przestarzałe.
Zamiast tego użyj:
źródło
Szybka implementacja porównywania typów
UWAGA: Zauważ, że działa również z protokołami, których obiekt może, ale nie musi, rozszerzać się
źródło
Wreszcie mam coś do roboty. Jest trochę leniwy, ale nawet trasa NSClassFromString () nie działała dla mnie ...
i bingo, „makeFoo” zawiera instancję Foo.
Wadą jest to, że twoje klasy muszą pochodzić z FactoryObject i MUSZĄ mieć metodę inicjalizacji Obj-C +, aby Twoja klasa została automatycznie wstawiona do mapy klas przez globalną funkcję "mapClass".
źródło
Oto kolejny przykład pokazujący implementację hierarchii klas, podobną do zaakceptowanej odpowiedzi, zaktualizowaną dla pierwszej wersji Swift.
Drukuje ten wynik:
źródło
var x: NamedItem.Type
jeśli przypiszęx = Folder.Type
, tox()
zwraca nowyNamedItem
, a nieFolder
. To sprawia, że technika jest bezużyteczna w wielu zastosowaniach. Uważam to za błąd .