2

I understand that

self.something

this is member value for that class. but what is

something.self
Kyo Heo
  • 141
  • 8
  • The syntax is a bit confusing because it originally comes from Objective-C where the `self` property was a property that returned the object itself. Basically, `SomeType.self` is explicitly saying that you want to pass `SomeType` as a parameter. – Sulthan Jan 22 '20 at 15:57
  • See [here](https://stackoverflow.com/questions/31438368/swift-whats-the-difference-between-metatype-type-and-self/41709040#41709040). Just read til the horizontal line. Beyond that isn't much related to your question – mfaani Jan 22 '20 at 15:58

1 Answers1

9

Consider code like

JSONDecoder().decode(what, from: myJSONData)

What goes where I have what? We have to tell the decoder what type of thing to expect to decode. Basically, what is the name of a type — the name of a class, struct, or enum that conforms to Decodable.

But how to say the name of a type? Let's suppose that the type of thing you expect to decode is String. Then what do you say here?

JSONDecoder().decode(String, from: myJSONData) // error

No, you can't just say the name of a type out of the blue like that. This is how you do it:

JSONDecoder().decode(String.self, from: myJSONData)

What you're really passing here when you say String.self is the metatype for String. And this example is exactly what it's for, i.e. when you need to pass a type as a parameter.

The declaration of this method signals this by using .Type:

func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable

The expression T.Type tells you that what you pass when you call this method should be Something.self.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • 1
    For some context as to why you can't just use `String` like you tried: Using typenames directly to refer to type objects leads to an ambiguity. Example: does `let x = [String]` mean `let x = Array` (a type object), or does it mean `let x = Array(arrayLiteral: String)` (a single-member array containing the `String` type object) – Alexander Jan 22 '20 at 16:34
  • @Alexander-ReinstateMonica I'd just say that String plain and simple is the type of an _instance_ to be passed here. When you declare `var s : String` you are saying "give me _a_ String (instance)". So clearly you can't use that same syntax when you want to pass String, _itself_. The `.self` suffix says exactly that! – matt Jan 22 '20 at 16:38
  • "So clearly you can't use that same syntax when you want to pass String, itself. " Nope, there's no reason why that couldn't be the case. You *could* design the language to overload the syntax to have two meanings, like how `()` is both a type and a value. – Alexander Jan 22 '20 at 16:40
  • @Alexander-ReinstateMonica Now, having said that, do I ever forget to add `.self` when calling `decode()` or implementing `layerClass` or whatever? Yes, all the time. :) So clearly my inner brain agrees with you: it expects that sort of overloading. – matt Jan 22 '20 at 16:40