Przetestowałem niektóre isa swizzling za pomocą Swift i stwierdziłem, że działa tylko wtedy, gdy NSObject jest super-klasą (bezpośrednio lub wyżej) lub używając dekoracji „@objc”. W przeciwnym razie będzie postępować zgodnie ze stylem static- i vtable-dispatch, jak C ++.
Czy definiowanie klasy Swift bez klasy bazowej Cocoa / NSObject jest normalne? Jeśli mnie to niepokoi, oznacza to rezygnację z dużej części dynamiki Objective-C, takiej jak przechwytywanie metod i introspekcja w czasie wykonywania.
Dynamiczne zachowanie w czasie wykonywania leży u podstaw takich funkcji, jak obserwatorzy właściwości, dane podstawowe, programowanie zorientowane na aspekty , przesyłanie wiadomości wyższego rzędu , struktury analityczne i rejestrowania itd.
Użycie stylu wywołania metody Objective-C dodaje około 20 operandów kodu maszynowego do wywołania metody, więc w pewnych sytuacjach ( wiele ciasnych wywołań metod z małymi treściami) wysyłanie statyczne i vtable w stylu C ++ może działać lepiej.
Ale biorąc pod uwagę ogólną zasadę 95-5 ( 95% wzrostu wydajności pochodzi z dostrojenia 5% kodu ), czy nie ma sensu zaczynać od potężnych funkcji dynamicznych i wzmacniać je tam, gdzie to konieczne?
źródło
Odpowiedzi:
Klasy Swift będące podklasami NSObject:
objc_msgSend()
do wywołań (większości) ich metodKlasy Swift, które nie są podklasami NSObject:
objc_msgSend()
do wywołań ich metod (domyślnie)Podklasa NSObject w Swift zapewnia elastyczność środowiska wykonawczego Objective-C, ale także wydajność Objective-C. Unikanie NSObject może poprawić wydajność, jeśli nie potrzebujesz elastyczności Objective-C.
Edytować:
W przypadku Xcode 6 beta 6 pojawia się atrybut dynamiczny. To pozwala nam poinstruować Swifta, że metoda powinna używać dynamicznego wysyłania, a zatem będzie wspierać przechwytywanie.
źródło
Odkryłem również, że opierając klasę Swift na NSObject, zauważyłem nieoczekiwane zachowanie w czasie wykonywania, które mogło ukryć błędy w kodowaniu. Oto przykład.
W tym przykładzie, gdy nie opieramy się na NSObject, kompilator poprawnie wykrywa błąd w testIncorrect_CompilerShouldSpot, zgłaszając „... 'MyClass' nie można zamienić na 'MirrorDisposition'”
W tym przykładzie, gdy opieramy się na NSObject , kompilator nie dostrzega błędu w testIncorrect_CompilerShouldSpot:
Wydaje mi się, że morał jest taki, że bazuj tylko na NSObject, gdzie naprawdę musisz!
źródło
Zgodnie z odniesieniem do języka, nie ma wymogu, aby klasy tworzyły podklasy dowolnej standardowej klasy głównej, więc w razie potrzeby można dołączyć lub pominąć nadklasę.
Zauważ, że pominięcie nadklasy w deklaracji klasy nie przypisuje żadnej domyślnej nadklasy bazowej. Definiuje klasę bazową, która w efekcie stanie się korzeniem niezależnej hierarchii klas.
Z odniesienia językowego:
Próba odniesienia
super
z klasy bez superklasy (tj. Klasy bazowej) spowoduje błąd czasu kompilacjiźródło
Uważam, że zdecydowana większość danych Swift nie będzie
objc
. Tylko te części, które muszą komunikować się z infrastrukturą Celu C, zostaną wyraźnie oznaczone jako takie.Nie wiem, w jakim stopniu introspekcja środowiska uruchomieniowego zostanie dodana do języka. Przechwytywanie metody będzie prawdopodobnie możliwe tylko wtedy, gdy metoda wyraźnie na to pozwoli. Zgaduję, ale tylko projektanci języków w Apple naprawdę wiedzą, dokąd zmierzają.
źródło
educated guesses
za kilka lat. Ale na razie to tylko duży znak zapytania.Poniższy tekst jest skopiowany z Apple's Swift-eBook i zawiera odpowiednią odpowiedź na Twoje pytanie:
Definiowanie klasy bazowej
Każda klasa, która nie dziedziczy z innej klasy, jest nazywana klasą bazową.
Klasy Swift nie dziedziczą po uniwersalnej klasie bazowej. Klasy zdefiniowane bez określania nadklasy automatycznie stają się klasami podstawowymi, na których można budować.
Odniesienie
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Inheritance.html#//apple_ref/doc/uid/TP40014097-CH17-XID_251źródło
To normalne. Spójrz na cele projektowe Swift: celem jest wyeliminowanie ogromnych klas problemów programistycznych. Swizzling metod prawdopodobnie nie jest jedną z rzeczy, które chcesz robić w Swift.
źródło