Lescai Ionel Lescai Ionel - 3 months ago 20
Swift Question

How to avoid using A.self?

Take this code:

protocol P: class {
static var hello: String { get }
}

class A: P {
class var hello: String {
return "Hello"
}
}

class B: A {
override static var hello: String {
return "Hello World"
}
}

class C: A {}

class D: C {
override static var hello: String {
return "Hello D"
}
}

func sayHello(elements: P.Type...) {
for p in elements {
print(p.hello)
}
}

func sayHelloAgain(elements: A.Type...) {
for p in elements {
print(p.hello)
}
}

func sayHelloThe3rd(elements: [A.Type]) {
for p in elements {
print(p.hello)
}
}

sayHello(A.self, B.self, C.self)
sayHelloAgain(A.self, B.self, C.self)


Compare it to this (taken from this presentation)

func register<T: UITableViewCell where T: ReusableView, T: NibLoadableView>(_: T.Type) { ... }
tableView.register(FoodTableViewCell)


Why do I have to use A.self in one case, but not in the other?
And also, don't need to use .self when calling with one argument.

sayHello(A)
sayHello(A, B) //doesn't compile

Answer

The .self is syntactic salt. It's not necessary from a technical perspective, but it exists to cause errors in code that's often a result of a typo, such as:

struct Foo { }

let foo = Foo

This code will give you a compiler error, telling you that either you need to complete the initializer/function/method call, or append .self if you meant to refer to the type.

In the latter example, the context deals exclusively with types and not values, so there's no chance of confusing one with the other, thus, .self isn't necessary.

Perhaps there's a way to modify the function declaration in your example so as to not require the .self, but I'm not aware of such a feature. I'd be interested to find out.