Swift is a great language to write applications in. However, being more or less proficient in numerous other programming platforms, one will of course acknowledge that one of the most flexible and truly powerful programming languages out there is ECMAScript. In this article I am going to talk about such a syntactic construct as the anonymous class. Consider this little gist.
This one is not the class in its entirety, but just the dynamic behavior I would occasionally end up looking for while working on a project. Here, in the
this will be pointing to the object constructed next to the
When it comes down to implementing anonymous classes in Swift, you can’t. There are life-hacks though!
Swift allows you to declare classes and structs directly in the execution contexts regardless of whether if it’s a closure object or an explicit function. This approach fits the case of the anonymous class perfectly: it’s a reference-type object implementation details and interface of which is visible only inside a certain execution scope. But here start the memes:
Swift is a statically typed language and the only possible interface visible in the outer scope which we can reference as a return type of such execution context is
Any. If you recall, EcmaScript, for comparison, is a dynamically typed language with all-around dynamic dispatching even in case of property access. The user of an object returned from this execution context essentially looks up the value of the member defined by name in an opaque dictionary and in case if the user’s assumptions about the inner workings and the structure of the returned object, let alone the value resulting from the lookup, happen to be invalid, a commonly accepted (and also defined by ECMAScript) implementation is to return
undefined of type
Oh, and if there are nested declarations and you expect to be able to chain several property look-ups, looking up anything in an
undefined value causes TypeError to be thrown by the runtime (this behavior is also strictly defined by ECMAScript).
Okay, it’s 12:07 AM, you know, I think I ama go get some sleep and proceed tomorrow, alright?
8:18 AM the same day. Well that was a terrible “night” experience: I was playing Asphalt 9 for two hours, then had a dream about chatting with Moo Snuckel. But let’s proceed.
Not-so-anonymous classes 2: Electric Boogaloo
Comparing this example with the previous, one easily notes appearance of a protocol that strictly denotes a public interface of the returned object. In swiftlang, at least today, with 4.2, all protocols are required to be defined in module scope and thus this method is very verbose since you can’t even hide this declaration in something else, say, an empty class called
But despite the need to explicitly specify an interface of the returned object instead of the object’s signature being deducted by the compiler from a dynamically created value, it does work though — the returned object is of passed-by-reference type.
swiftlang does indeed lack syntactic tools for anonymous class or inline protocols and I find it rather funny because there are in fact anonymous structs. Okay, alright, actually, no, from the point of the language, those are actually called variable-sized tuples. They are passed by value copying, by the way, because on runtime they are actually structs. Mind you, they do lack a lot of features that syntactic structs have. Simplest examples are, of course, static extensions, methods, static methods and property accessors.
You may or may not have used tuples already, for instance with
PublishRelay that had a generic element type of
Void and you would pass an empty tuple to the
accept(value:) method of the relay. Or, alternatively, returning multiple values from a function by returning a tuple containing those values causing only an inevitable overhead of copying values around.
Okay, so I have proceeded to write a gist and realized that swiftlang prohibits single value tuples, lol. Well, I’ll just add something then.
The obvious advantage is being short.
A sidestep here is that in majority of cases in Swift an execution context’s return type is not derived from the returned value and the function’s or closure’s signature must be specified explicitly. Same behavior returns when types are known, but the parsing context allows for ambiguity through, for instance, multiple methods with nearly same type signatures as can be seen here.
The major point however, why this approach fits NOT is that it’s a passed-by-value object. We could go on to even have functions in form of closures and 10 more values in the tuple — well they all will be aggressively copied around. Also, please note how I explicitly said functions and not methods, because a tuple is not an object-oriented programming compliant primitive.
Not quite what we are looking for, right? If only there was a passed-by-reference “medium” (hah, get it?) that we could use as
Closure scope based anonymous structs
Actually, there is one such passed-by-reference medium in Swift.
Recall how one could implement a closure in an arbitrary programming language: is the number of closure objects hypothetically finite for a given moment in program’s lifecycle? If yes, store all captured objects statically, if not, utilize dynamic allocation. This technique is to make sure that captured objects’ lifecycles exceed scope in which they have been created. I.e., an object gets captured by a closure and leaks outside of the functions scope in a deliberate manner (and regardless of allocation strategy).
If by any coincidence the desired language supports OOP, then you are in for a treat because the behavior described in the previous sentence can easily be achieved with putting the references to the captured objects into the object’s properties — and boom, here is the closure with captures. Need to get access from any of the methods to the current arrangement of captured objects aka context?
self ‘dot’ whatever member name.
Oh, but then you actually realize that clang compiler, when having the blocks extensions enabled, has such a feature as a separate storage type called
__block which, you wouldn’t believe, is used to denote that in case if an object of this storage type is referenced inside a block, this means that it must be stored not in the function’s execution scope, but in a dynamically allocated anonymous container containing all of the objects captured by the blocks created in the current execution scope. There is strictly only one such container per execution context so if there are multiple blocks, their captures refer to the same objects.
coughs “a dynamically allocated anonymous container”, you say? Well this is sort of similar to that OOP closure implementation approach we have seen a paragraph earlier, isn’t it, except
self turns out to be implicit and duct in by the compiler to point wherever this “anonymous container” is. I wonder if we could have such thingie in swiftlang!
Spoiler, we have, and in Swift this behavior is implicit.
You still have to specify the return type of the function explicitly. And also, the returned value is passed-by-value. Worry not, a swift closure, just like clang block, is a passed-by-reference object — to spell out, it means, that references to closures are copied, with 2 members inside of the struct, 2 closures.
Thank you immensely for reading, I’d be glad if you check in in the comment section and share your thoughts :)
Anonymous classes in PHP
A perfect case of anonymous class in PHP. Despite the language being dynamic, the code is treated as correct only in case if the public methods and properties are actually present in the declaration. Provided by my fellow Laravel enthusiast.
C++ nested classes
The closest I have ever gotten, once again, the compiler is kind enough to provide type-checking.
Block-based OOP in C with blocks
Can not have anonymous return type declaration in
foo though, since 2 anonymous struct declarations are not equivalent.
Lamda expressions and tuples-based anonymous classes in C++14
This one is just for lolz because if you dig down to all the ways in Cpp by which you can reinvent OOP, it will take 6 separate Medium articles.
The article has started out as a nerdy discussion with a fellow Laravel enthusiast.
This also fits as a motivation for writing this article. Compare the code base of these 2 commits:
The former one is the shitty one.
The goal of both manipulations was to make the method
RxNick class accept not already constructed values of type URL, method and everything else, but rather some objects that can lazily produce the values of these types. First implementation represents those as explicit classes with factory methods. I have done did implemented, but then realized, I ain’t even need no inheritance or common protocols, or even having these things as explicit entities. I have proceeded to revert that commit and then have built the latter implementation using closures. Works like a charm, moreover illustrates the extent to which these closures ARE in fact anonymous classes.