Thursday, December 8, 2016

Method Dispatch in Swift

Brian King:

Compiled programming languages have three primary methods of dispatch at their disposal: direct dispatch, table dispatch, and message dispatch, which I explain below. Most languages support one or two of these. Java uses table dispatch by default, but you can opt into direct dispatch by using the final keyword. C++ uses direct dispatch by default, but you can opt into table dispatch by adding the virtual keyword. Objective-C always uses message dispatch, but allows developers to fall back to C in order to get the performance gains of direct dispatch. Swift has taken on the noble goal of supporting all three types of dispatch. This works remarkably well, but is a source of confusion to many developers, and is behind a number of gotchas that most Swift developers have encountered.

[…]

So, how does Swift dispatch methods? I haven’t found a succinct answer to this question, but here are four aspects that guide how dispatch is selected:

  • Declaration Location
  • Reference Type
  • Specified Behavior
  • Visibility Optimizations

[…]

Above, I mentioned that methods defined inside the initial declaration of an NSObject subclass use table dispatch. I find this to be confusing, hard to explain, and in the end, it’s only a marginal performance improvement.

Swift extensions use direct dispatch (less dynamic than in the class declaration), while NSObject extensions use message dispatch (more dynamic than in the class declaration). Then he gives an example where an NSObject override method is not called because it’s in an extension rather than directly in the subclass; the location of the initial declaration matters. Also, you can override NSObject extension methods but not Swift ones. And don’t forget protocols. It’s all rather confusing.

Update (2016-12-10): See also: Ling Wang.

2 Comments RSS · Twitter

I didn't think final avoids table dispatch in Java. After all a final method can still have ancestors, and when you call the method it might be on an object variable of the ancestor. Am I wrong?

@John Say that you have a variable of type String. Java is strongly typed, so you know it really is a String, not an ancestor type such as Object. And String is final so you know it’s not holding a descendent type. So I think it really can use direct dispatch.

Leave a Comment