In ObjC
, it is using Messaging
, static binding
, dynamic typing
, dynamic binding
, dynamic method resolution
, dynamic loading
, introspector
and so on.
Importantly, the core method objc_msgSend
is responsible for taking the selector you're sending and the object you're sending it to, and looking that up in the class method tables to figure out exactly which piece of code is supposed to handle it.
My concerns here are:
Is Swift
doing something similar like ObjC
on runtime?
How does Swift runtime
find the implementation code for some object/class method?
In ObjC
, classes
and objects
are compiled to some runtime types
such as C struct
on runtime. Then what are such classes
and objects
compiled to on runtime in Swift
?
Does Swift runtime
have something like class / meta class / isa pointer / super pointer
?
The Swift runtime exports standard metadata objects for Builtin types as well as standard value witness tables that can be freely adopted by types with common layout attributes.
Even when written without a single line of Objective-C code, every Swift app executes inside the Objective-C runtime, opening up a world of dynamic dispatch and associated runtime manipulation.
That's where the @objc attribute comes in: when you apply it to a class or method it instructs Swift to make those things available to Objective-C as well as Swift code.
Use Selectors to Arrange Calls to Objective-C Methods In Objective-C, a selector is a type that refers to the name of an Objective-C method. In Swift, Objective-C selectors are represented by the Selector structure, and you create them using the #selector expression.
In short there are Dynamic and Static types of method call dispatching.
Static - the function address to be called is determined in the compilation time, so that expense of such call is similar to C-function calling. This mechanism is used for private
methods or final
classes methods call dispatching.
Dynamic dispatching is mechinism which allows to implement polymorphism concept of OOP - the function address to be called is determined in running time. Swift has two subtypes of it:
2.1. Obj-C - you already described in the question. This mechanism is used when object inherits from NSObject or calling method has @objc prefix.
2.2. Virtual table based (like in C++) - there is similar witness tables. What it does during method call dispatching is just single arithmetic operation - calculation of actual function address based on function offset in the base class witness table and the object class witness table location. So that's a relatively cheap operation comparing to Obj-C. It explains why "pure" Swift approximates to C++ performance.
If you don't mark you method with private
keyword or your class is not final
and same time you class is "pure" Swift (it does not inherit NSObject) then this virtual table based mechanism is used. It means that all the methods by default are virtual
.
P.S. Helpful link for proving my vision regarding "Types":
https://developer.apple.com/swift/blog/?id=27
"Subtypes" explanation is based on my understanding.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With