[swift-users] Why can't Swift instance methods call class methods without qualification?

Brent Royal-Gordon brent at architechies.com
Fri Jul 1 17:17:06 CDT 2016

> On Jun 30, 2016, at 5:59 PM, Rick Mann via swift-users <swift-users at swift.org> wrote:
> Why do I have to call MyClass.classMethod()? Just a choice made by the language designers to distinguish the call at the call site? I like C++'s way of treating all static methods as directly available to the instance.

There are two kinds of OO languages: ones with metatypes and ones without them.

Basically, in C++ a class is a thing that exists at compile-time. You can't create a variable that contains "a class" or pass "a class" to a function. RTTI gives you access to an object *describing* a class, but this is not the class itself, any more than a map of California is California.

In many other languages, including Swift, this is not the case. A class is itself an object that exists at runtime. The class object is an instance of a "metaclass", a second class which parallels the original class; its class/static members are actually metaclass instance members. That means you can get the class instance, assign it to variables, pass it around, call static methods on it, and call initializers on it to create new instances. You might think of it this way: Every class inherently comes with a singleton, which provides access to all static members and factory methods for all initializers.

(In Swift, which has non-object types, the terminology is actually a little different from normal: the "class object" is a "type instance", and the "metaclass" is a "metatype". A type `Foo` has a metatype called `Foo.Type`. You can retrieve any instance's type instance with `foo.dynamicType`, or retrieve a type's type instance with `Foo.self`.)

If you adopt this design, then treating instance methods and class methods as belonging to different namespaces is the most straightforward way to design the language. Instance methods belong to the class and are called on instances, while class methods belong to the metaclass and are called on class objects. You wouldn't expect `someFoo.bar()` to call a method on `Foo`'s class object any more than you would expect it to call a method on `someBaz`.

You *could* make that work, of course, but it would be wholly artificial. Languages which do put class and instance methods in the same namespace—C++, Perl, Python—usually do so because that falls out naturally from their own designs.

If the above was too dense and jargony:

1. Sorry.

2. This is common behavior in many OO languages. Off the top of my head, Ruby, Objective-C, and C# all behave the way Swift does.

3. This behavior falls naturally out of some very deep—and very desirable—features of Swift's design. If it were changed, the change would be a hack.

Brent Royal-Gordon

More information about the swift-users mailing list