协议关联类型和<>

时间:2018-10-29 08:36:48

标签: swift generics protocols

在swift协议中使用泛型函数或associatedType有什么区别?

protocol Repository {
    associatedtype T
    func add(data : T) -> Bool
}

protocol Repository {
    func add<T>(data : T) -> Bool
}

3 个答案:

答案 0 :(得分:4)

定义的关联类型使符合协议的类成为强类型。这样可以提供编译时错误处理。

另一方面,泛型使符合协议的类更加灵活。

例如:

protocol AssociatedRepository {
    associatedtype T
    func add(data : T) -> Bool
}

protocol GenericRepository {
    func add<T>(data : T) -> Bool
}


class A: GenericRepository {
    func add<T>(data : T) -> Bool {
        return true
    }
}

class B: AssociatedRepository {
    typealias T = UIViewController
    func add(data : T) -> Bool {
        return true
    }
}

A可以将任何类放入add(data:)函数中,因此您需要确保该函数能够处理所有情况。

A().add(data: UIView())
A().add(data: UIViewController())

都是有效的

但是对于类B,当您尝试放置除UIViewController之外的任何内容时,都会出现编译时错误

B().add(data: UIView()) // compile-time error here
B().add(data: UIViewController())

答案 1 :(得分:3)

  • associatedtype是struct / class中的静态类型,它通过typealias声明或类型推断采用协议。该类的类型始终相同。

  • 泛型可以是任何东西,甚至可以是同一类中的不同类型。

答案 2 :(得分:2)

这种情况

protocol Repository {
    func add<T>(data : T) -> Bool
}

编译器将其理解为:“任何传递给func add的类型都是可以接受的,该函数的结果将是Bool

但是这个

protocol Repository {
    associatedtype T
    func add(data : T) -> Bool
}
编译器将

理解为:“ func add仅接受typealias T = ...中定义的类型并返回Bool

在第二种情况下,您仅将泛型参数限制为类型别名类型。

在协议的多个功能中使用通用参数时,将显示另一个重要功能。在这种情况下,它保证func add<T>func multiply<T>具有相同的类型T。如果是通用功能,则不能保证。

protocol Calculable {
    associatedtype T
    func add<T>(a: T, b: T) -> T
    func multiply<T>(a: T, b: T) -> T
}
// In this case you know that T is the same for all functions

protocol CalculableDifferent {
    func add<T>(a: T, b: T) -> T
    func multiply<T>(a: T, b: T) -> T
}
// In this case add can accept One type, when multiply can accept Another