2

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.

Pritt Balagopal
  • 1,476
  • 2
  • 18
  • 32
  • 1
    By defining ```Animal.Type``` you just pass parameter type you can not use t parameter member inside the function without creating an object. You can check this : https://stackoverflow.com/a/41709040/14733292 – Raja Kishan Jun 23 '21 at 05:08
  • 2
    I _think_ this is just an aesthetic choice of language design, rather than because of some technical difficulties. It is to make it absolutely clear what is a _type_, and what is a _value_ representing a type. – Sweeper Jun 23 '21 at 05:12
  • @RajaKishan That link certainly does help a bit in understanding, but I'm still confused as to why `.self` was even needed. Thanks for your help, nonetheless. – Pritt Balagopal Jun 23 '21 at 05:16
  • 1
    @PrittBalagopal I have asked a similar one to your question. Please check it out https://stackoverflow.com/q/65369113/14531220 – zeytin Jun 23 '21 at 05:28

1 Answers1

1

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.

Pritt Balagopal
  • 1,476
  • 2
  • 18
  • 32