Using type as a value, why is the "self" keyword required here?

Viewed 71

I'm currently learning type as a value in functions and wrote this sample code to play around:

import Foundation

class Animal {
    func sound() {
        print("Generic animal noises")
    }
}

func foo(_ t:Animal) {
    print("Hi")
}

foo(Animal) //Cannot convert value of type 'Animal.Type' to expected argument type 'Animal'

I'm not surprised by this result. Obviously you cant pass the type itself as an argument where an instance of that type is expected. But notice that the compiler says that the argument I passed was of type Animal.Type. So if I did this, it should compile right?

func foo(_ t:Animal.Type) {
    print("Hi")
}

foo(Animal) //Expected member name or constructor call after type name

This is what really confuses me a heck ton, the compiler told me it was of type Animal.Type *but after making this change it once again shows an error.

Of course I listened to the fix Swift suggests and do:

foo(Animal.self) //Works correctly

But my biggest question is: WHY? Isn't Animal itself the type? Why does the compiler require me to use Animal.self to get the type? This really confuses me, I would like for some guidance.

1 Answers

Self-answering, with help of comments, I was able to find out the reason:


Using .self after the type name is called Postfix Self Expression:

A postfix self expression consists of an expression or the name of a type, immediately followed by .self. It has the following forms:

expression.self
type.self

The first form evaluates to the value of the expression. For example, x.self evaluates to x.

The second form evaluates to the value of the type. Use this form to access a type as a value. For example, because SomeClass.self evaluates to the SomeClass type itself, you can pass it to a function or method that accepts a type-level argument.

Thus, the .self keyword is required to consider the type as a value capable of being passed as an argument to functions.

Related