swift - 将通用参数限制为从协议(protocol)继承的协议(protocol)

标签 swift generics inheritance protocols

我不确定哪个 where 子句可以将泛型参数限制为从某个协议(protocol)继承的协议(protocol)。

protocol Edible {}
protocol PetFood: Edible {}
struct CatFood: PetFood {}
struct Rocks {}

func eat<T: Edible>(_ item: T) -> String {
    return "Just ate some \(type(of: item))"
}

let food: CatFood = CatFood()
eat(food) //"Just ate some CatFood"

let moreFood: PetFood = CatFood()
//eat(moreFood) //Cannot invoke 'eat' with an argument list of type '(PetFood)'

func eatAnything<T>(_ item: T) -> String {
    return "Just ate some \(type(of: item))"
}

eatAnything(moreFood) //This works, obviously
eatAnything(Rocks()) //But, of course, so does this...

有什么方法可以限制 eatAnything() 允许协议(protocol)类型,但仅限那些继承自 Edible 的协议(protocol)类型?

最佳答案

在您的示例中,泛型函数的定义没有任何意义,因为它可以替换为:

func eat(_ item: Edible) -> String {
    return "Just ate some \(type(of: item))"
}

但是如果你真的想使用泛型函数那么你应该知道:

  1. 泛型函数的定义

    • func eat<T: Edible>(_ item: T) -> String { ... }
    • func eat<T>(_ item: T) -> String where T: Edible { ... }
    • func eat<T: Edible>(_ item: T) -> String where T: Equatable { ... }
  2. 协议(protocol)是动态类型,因此它们使用后期绑定(bind)。通用代码在编译期间被转换为普通代码,需要早期绑定(bind)

    • 早期绑定(bind) (编译时):类型在运行时运行变量之前已知,通常通过静态的声明方式
    • 后期绑定(bind) (运行时):在运行时执行变量之前,类型是未知的;通常通过赋值,但还有其他方法来强制类型;动态类型语言将此称为底层功能
  3. 通用函数可以定义为与协议(protocol)兼容的类型,但此函数不能将此协议(protocol)作为类型传递,因为编译器不知道该类型是什么T .传递给泛型函数的类型必须是特定类型(类、结构、枚举……)


let a: [Int] = [1,2,3]
let b: [CustomStringConvertible] = [1, "XYZ"]

a.index(of: 2) // 1
b.index(of: "XYZ") // error

关于swift - 将通用参数限制为从协议(protocol)继承的协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46260511/

相关文章:

json - 在 Swift 中使用 ObjectMapper 中的 TranfsformType 映射类对象

c++ - 主类不能从我的第二类继承方法

ios - 新 View 中的 Swift 动画立即发生

arrays - 如何使 Array<Any> 相等?

C# 泛型不识别类型

c# - 通用约束如何防止使用隐式实现的接口(interface)对值类型进行装箱?

scala - < : 的特征继承

Javascript:名为 "name"的属性在 chrome/ff 中为空,在 IE 中则不然

ios - 如何在 searchBar 中设置 http 不区分大小写?

iOS:如何在框架内加载 xib