bhartsb
bhartsb

Reputation: 1366

Why is typealias needed for conformance to a protocol

The swift language guide gives this protocol:

protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}

with this conforming struct:

struct IntStack: Container {
    // original IntStack implementation
    var items = [Int]()
    mutating func push(_ item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }
    // conformance to the Container protocol
    typealias Item = Int
    mutating func append(_ item: Int) {
        self.push(item)
    }
    var count: Int {
        return items.count
    }
    subscript(i: Int) -> Int {
        return items[i]
    }
}

Why is typealias Item = Int needed? It seems that "Item" can be inferred already.

Upvotes: 1

Views: 200

Answers (3)

Rob Napier
Rob Napier

Reputation: 299275

I agree with Evgeniy that the typealias here isn't needed, but there are cases where it is, specifically if the typealias is not part of any signature. For example, the following is a legal protocol:

protocol Container {
    associatedtype Item
}

The only way to conform to that would be with a typealias. In this form it doesn't seem too useful, but consider types with static properties:

protocol ConfigurationType {
    static var values: [String: String] {get}
}

protocol Configurable {
    associatedtype Configuartion: ConfigurationType
}

I'm not suggesting this particular example is a good use of protocols, but it is legal.

I agree that the documentation here is a bit confusing, but I also wouldn't necessarily use type-inference here. I'd generally suggest using the typealias, but also using it in the methods:

// conformance to the Container protocol
typealias Item = Int
mutating func append(_ item: Item) {
    self.push(item)
}
var count: Int {
    return items.count
}
subscript(i: Int) -> Item {
    return items[i]
}

But this is a debatable point.

Upvotes: 0

mohsen
mohsen

Reputation: 5058

I don't know why swift.org use associatedtype like that but generally swift.org define associatedtype as following:

An associated type gives a placeholder name to a type that is used as part of the protocol

and here is the right sample

protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}

struct IntStack: Container {
    // original IntStack implementation
    var items = [Int]()
    mutating func push(_ item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }
    // conformance to the Container protocol
    typealias Item = Int
    mutating func append(_ item: Item) {
        self.push(item)
    }
    var count: Item {
        return items.count
    }
    subscript(i: Item) -> Item {
        return items[i]
    }
}

I guess it's a mistake of swift.org's content maker

Upvotes: 0

Ievgen Leichenko
Ievgen Leichenko

Reputation: 1317

You are actually right. The Item type can be inferred, and typealias Item = Int is not needed.

You can remove that line and see, that the code compiles.

Upvotes: 2

Related Questions