In the process of learning the swift language, you will constantly find some unbelievable syntax of swift. After learning it, I often ask myself, “Is it really necessary? Before learning it, who would have thought that self and Self are different?

Keyword self

Scenario 1 Prefix self.

The prefix self. is the most commonly used scenario, when the keyword self, similar to the this keyword in other languages, represents the instance of the current code run during the coding process.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Foo {
    private var name: String = ""
    init(_ name: String) {
        self.name = name //The attribute name is ambiguous with the parameter name and is explicitly specified by self.
    }

    func show() {
        print("name = \(name)") //When there is no ambiguity, it is sufficient to use the attribute name directly
    }
}

Note that the prefix self. represents an instance object of the current type. In type definitions, if the prefix self. appears in an embedded type or anonymous function, be aware of what it refers to. This is somewhat similar to the confusing this in es6.

In es6, the keyword this, has nothing to do with functions, objects or classes, but only with the execution context.

1
2
3
4
5
6
7
extension Foo {
    //Add a computed property Assignment by anonymous function, internal access prefix self. property
     var age: Int = {
        //print(self.name) //In swift 5.7 it will prompt an error Unable to find self object
        return 25
    }()
}

Scenario 2 postfix .self

You can use the postfix self expression to access a type as a value. For example, SomeClass.self returns SomeClass itself, not an instance of SomeClass. And SomeProtocol.self returns SomeProtocol itself, not an instance of a type that conforms to SomeProtocol at runtime.

postfix .self, returns the corresponding type (type), not the instance (instance).

The most common place to see this is in object deserialization operations, such as :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
struct Foo: Codable {
    let name: String
}

let decoder = JSONDecoder()

//The return value is the Foo type instance
let json = """
{
    "name": "Durian"    
}
""".data(using: .utf8)!

//func decode<T>(T.Type, from: Data) -> T 
let foo = try decoder.decode(Foo.self, from: json)

Looking at the function definition of decode, you can see that Foo.self represents a meta-type of type Foo.

Keyword Self

When I first saw the Self keyword, I thought it was the same thing as self, so I should just pay attention to the prefix and postfix. However, looking at the context, the symbol . does not appear at all where Self is used.

The Self type isn’t a specific type, but rather lets you conveniently refer to the current type without repeating or knowing that type’s name.

In a protocol declaration or a protocol member declaration, the Self type refers to the eventual type that conforms to the protocol.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Foo {
    private var name: String = ""
    required init(_ name: String) { // Add required keyword
        self.name = name 
    }

    func show() {
        print("name = \(name)") 
    }
}

Extends a single property:

1
2
3
4
5
extension Foo {
    static var jay: Self { 
        Self("jay")
    }
}

The Self keyword is a simple way of writing code for the type Foo and has no other properties of its own.