为什么要使用类型别名才能符合协议

时间:2019-11-01 04:26:53

标签: swift generics

swift language guide给出了以下协议:

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: Int) {
        self.push(item)
    }
    var count: Int {
        return items.count
    }
    subscript(i: Int) -> Int {
        return items[i]
    }
}

为什么需要typealias Item = Int?看来“物品”已经可以推断出来了。

3 个答案:

答案 0 :(得分:2)

您实际上是对的。可以推断为public bool findSet(int[] arr) { HashSet<Integer> set = new HashSet<>(); int count = 0; for(int n : arr) { if(set.contains(n)) count++; else set.add(n); } return count == 2; } 类型,不需要Item

您可以删除该行并查看代码是否已编译。

答案 1 :(得分:0)

我不知道为什么swift.org使用诸如此类的associatedtype,但是通常swift.org定义如下的associatetype:

  

关联的类型将占位符名称赋予用作   协议的一部分

这是正确的示例

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]
    }
}

我想这是swift.org内容制作者的错误

答案 2 :(得分:0)

我同意叶夫根尼(Evgeniy)的观点,此处不需要使用别名,但是在某些情况下,特别是如果该别名不是任何签名的一部分,则可以使用。例如,以下是合法协议:

protocol Container {
    associatedtype Item
}

唯一符合此要求的方法是使用typealias。在这种形式下,它似乎不太有用,但是请考虑具有静态属性的类型:

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

protocol Configurable {
    associatedtype Configuartion: ConfigurationType
}

我并不是说这个特定示例很好地使用了协议,但这是合法的。

我同意这里的文档有点混乱,但是我也不必在这里使用类型推断。我通常建议使用typealias,但也可以在方法中使用它:

// 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]
}

但这是有争议的一点。