Swift language statically or dynamically dispatched?
Describing C++, Java, and C# as statically dispatched is not particularly accurate. All three languages can and often do use dynamic dispatch.
Swift, similarly, can do both. It does differ from ObjC in that it does not always dynamically dispatch. Methods marked @final can be statically dispatched, as can struct and enum methods. I believe non-final methods can be statically dispatched if the runtime type can be proven at compile time (similar to C++ devirtualization), but I'm not certain about the details there.
Is Swift a dynamic or static language?
It is static - very static. The compiler must have all information about all classes and functions at compile time. You can "extend" an existing class (with an extension
), but even then you must define completely at compile time what that extension consists of.
Objective-C is dynamic, and since, in real life, you will probably be using Swift in the presence of Cocoa, you can use the Objective-C runtime to inject / swizzle methods in a Swift class that is exposed to Objective-C. You can do this even though you are speaking in the Swift language. But Swift itself is static, and in fact is explicitly designed in order to minimize or eliminate the use of Objective-C-type dynamism.
How do we determine a language is dynamic or static? an example is Swift
I've never heard of the term "static language" or "dynamic language." The usual terms I've heard of are "statically typed language" or "dynamically typed language."
"Dynamic" isn't a defined term in this context, so there's not much to say here.
Polymorphism has multiple different meanings, so I'll assume you mean subtype polymorphism. In that case, yes, dynamic dispatch is necessary. The whole idea is that you want objects of different types to behave in their own way in response to the same message (method call). The only way to do this is to decouple messages and function invocations, so that an appropriate function can be called at runtime depending on the type of the receiver of the message.
Swift is a statically typed language, through and through. This might be obscured a bit by type inference. If you have an expression like
func someFunction() -> Int { return 123 }
let x = someFunction()The type inference doesn't mean "
x
has some type that will be figured out at runtime." To the contrary, it means "The type ofx
can be deduced at runtime because we already know the type ofsomeFunction
."All types in Swift are known at compile time. In the worst case, a must at least have type
Any
, which is still a type. It's not a particularly useful type (because there isn't much anAny
is guaranteed to be able to do), but it's still a type.There is some confusion in that there's talk of types at compile time and runtime types. Here's an example:
class Car {
func vroom() { print("vroom") }
}
class SportsCar: Car {
override func vroom() { print("VROOOOOM") }
}
let car: Car = SportsCar()
func driveSportsCar(_: SportsCar) { print("driving") }
// Compile types are what determine usage compatibility
driveSportsCar(car) // cannot convert value of type 'Car' to expected argument type 'SportsCar'
// Runtime types are what determine method implementations
car.vroom() // => "VROOOOOM"In this example,
car
has a compile time type ofCar
, and a runtime type ofSportsCar
. The compile time type determines how it can be used, where it can be passed, etc. For example, you couldn't passcar
to adriveSportsCar()
function, because even though its runtime type isSportsCar
, its compile time type isCar
, which isn't compatible.The runtime type of an object is what determines the method implementations to be called.
Dynamic/runtime dispatch in Swift, or the strange way structs behave in one man's opinion
In your first example you're overriding the description
property. This implementation is therefore added to OddString
's vtable (as it's a class), and can be dynamically dispatched to just fine, regardless of what the instance is statically typed as.
In your second example, you don't have a class – so no vtables. However you are conforming to a protocol. Protocols allow for dynamic dispatch via protocol witness tables (see this great WWDC talk on them), however this only happens for implementations of protocol requirements.
localizedDescription
isn't a protocol requirement of the Error
protocol, it's merely defined in a protocol extension of Error
when you import Foundation
(this is documented in SE-0112). Therefore it cannot be dynamically dispatched. Instead, it will be statically dispatched – so the implementation called is dependant on the static type of the instance.
That's the behaviour you're seeing here – when your explosive
instance is typed as TestError
, your implementation of localizedDescription
is called. When typed as Error
, the implementation in the Error
extension is called (which just does a bridge to NSError
and gets its localizedDescription
).
If you want to provide a localised description, then you should conform your error type to LocalizedError
instead, which defines errorDescription
as a protocol requirement – thus allowing for dynamically dispatch. See this Q&A for an example of how to go about this.
Swift which method dispatch is used?
This method can be statically dispatched, because aaaa
has one fixed, statically-known type (AAA
).
If you instead had something like anyBBBB: any BBBB = aaa
, then calling anyBBBB.printSome()
would need dynamic dispatch, because it's not known which concrete type is involved until runtime. (Of course, if the compiler's data-flow analysis can prove there's only one possible type in that spot, then it can switch back to static dispatch. This is called Devirtualization)
Are public swift functions on ObjC objects dynamically or statically dispatched?
The Swift compiler will try to prove that a call to a method can only end up with a single implementation. If it can prove this then it will use static and not dynamic dispatch. Use of the "final" or "private" keyword, and whole module optimisation, will help with this.
why static dispatch so quickly in swift
You are confusing two separate concepts.
Static dispatch refers to the way a method body is called at runtime. If you have a class that could potentially have subclasses or any object where all you know about it is that it conforms to a certain protocol, you have to use dynamic dispatch, which means you have to look up the address of the method in a table (called a vtable or a witness table) and then jump to that location. If the compiler knows exactly what kind of object it has, e.g. a struct
, a final
class or a final
method in a class, it knows the method cannot be overridden and can therefore directly jump to its address without doing the lookup.
A method that is declared static
is a type method. It will be called on the type itself rather than an instance of the type i.e. inside the method self
refers to the type not an instance of the type.
static
methods can't be overridden so the compiler always knows the address at compile time and will use static dispatch for them. There's no need for any kind of hash table or witness table.
What is the difference between static func and final class func in swift
Just because a final
class function can't be overridden doesn't mean it's statically dispatched. A final class function be override a superclass non-final class function. Such a method call must be dynamically dispatched.
static
is merely an alias for final class
. They behave the same:
class C1 { class func foo() {} }
class C2: C1 { override final class func foo() {} }
class C3: C1 { override static func foo() {} }
Related Topics
API Violation - Multiple Calls Made to -[Xctestexpectation Fulfill]
Ambiguous Use of Operator '-' in Swift with 'Abs()'
Swift/Cloudkit: After Record Changed, Upload Triggers "Service Record Changed"
How to Properly Calculate 1 Second with Deltatime in Swift
Navigationview Bar Material Invisible on iOS 15
How to Set Avaudioengine Input and Output Devices (Swift/Macos)
How to Initialize a Unichar Variable in Swift
Using Nil-Coalescing Operator with Try? for Function That Throws and Returns Optional
Using Iboutlet from Another Class in Swift
Can't Use In/Contains Operator with Collection'
How to Unwrap Arbitrarily Deeply Nested Optionals in Swift
How to Skip Iterations of a For-In Loop (Swift 3)
Generic Within a Generic in Swift
How to Customize the Title/Subtitle Font in Callout from Mkannotationview or Just Hide Them
Swift Cannot Assign to Self in a Class Init Method
Ar with iOS: Putting a Light in the Scene Makes Everything Black