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

Rick Mann rmann at latencyzero.com
Fri Jul 1 17:24:44 CDT 2016


> On Jul 1, 2016, at 15:17 , Brent Royal-Gordon <brent at architechies.com> wrote:
> 
>> 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.

Hmm. It sounds like you're saying it is the way it is as a side-effect of the language implementation.

Maybe it's just my C++ upbringing, but it seems very counter-intuitive to me. A class method and an instance method look very much the same: they're defined in the same place (inside a class), and differ only in the "class" keyword. Sure, the class method can't access the instance variables, but it seems very, very natural that the instance can access the class, because the knowledge is available right there (either the implicit "self" or the instance variable used to call the method both have an obvious type).

In the same way that "self" is implicit in front of a method call from within the class, so to should be the class name in front of a class method call. That to me is consistent not only with Swift, but with other languages.

I've always found it annoying that Objective-C couldn't do this, either, but it has so many weirdnesses I just chocked it up as yet another.

-- 
Rick Mann
rmann at latencyzero.com




More information about the swift-users mailing list