gpt4 book ai didi

swift - 使类扩展符合通用协议(protocol)功能

转载 作者:搜寻专家 更新时间:2023-11-01 06:18:15 28 4
gpt4 key购买 nike

* 简短版 *

如何使类(扩展)符合通用协议(protocol)函数?

* 长版 *

这是支持分页集合的数据结构的一小部分,

protocol Pageable { 
//an object whose can be in a collection
}

protocol Page{ //a page of a collection that can be paginated

associatedtype PageItemType

func itemAt<PageItemType:Pageable>(index: Int) -> PageItemType
}

//Bonus question
//class PagedCollection<PageType:Page, ItemType:Pageable> {
//...
//}

这里是一个“真实”案例的协议(protocol)实现:

class Person : Pageable{}

class People {
var people: [Person]?
}

//Mark: - Page

extension People: Page{ /*** error 1 ***/

typealias PageItemType = Person

func itemAt(index: Int) -> Person{
let person : Person = self.people![index]
return person
}
}

获取以下错误 (1):

Type 'People' does not conform to protocol 'Page'

Protocol requires nested type 'PageItemType'

我也试过让它明确,但我只是得到了一个不同的错误:

//Mark: - Page

extension People: Page{

typealias PageItemType = Person

func itemAt<PageItemType:Pageable>(index: Int) -> PageItemType{
let person : Person = self.people![index]
return person /*** error 2 ***/
}
}

获取以下错误 (2):

Cannot convert return expression of type 'Person' to return type 'PageItemType'

那么:*如何让 itemAt 函数为 PageItemType 类型别名返回一个有效类型?

* 奖金 *

Bonus question 值(value) 50 赏金(如果答案超过一行,我将打开一个新问题):引用第一个代码片段PagedCollection

  • 鉴于每个 Page 实现始终具有 Pageable 协议(protocol)对象类型的已知实现
  • 有没有办法避免声明 ItemType:Pageable ?或者至少用 where 子句强制执行?

最佳答案

您似乎将关联类型与泛型函数混为一谈。

通用函数允许您在调用站点(即调用函数时)提供一个类型来替换给定的通用占位符。

关联类型允许符合协议(protocol)的类型提供自己的类型来替换协议(protocol)要求中给定的占位符类型。这是按类型完成的,而不是在任何函数的调用点。如果您希望对 associatedtype 强制执行一致性要求,您应该直接在其声明中这样做(即 associatedtype PageItemType : Pageable)。

如果我正确理解您的要求,您的itemAt(index:) 函数应该是非通用的(否则您协议(protocol)中的associatedtype 是完全多余的)。它返回的类型由符合 Page 的类型的实现定义,而不是由函数的调用者定义。例如,您的 People 类定义了 PageItemType 关联类型应该是 Person – 这就是 itemAt(index:) 应该返回。

protocol Pageable {/* ... */}

protocol Page {

// any conforming type to Page will need to define a
// concrete type for PageItemType, that conforms to Pageable
associatedtype PageItemType : Pageable

// returns the type that the implementation of the protocol defines
// to be PageItemType (it is merely a placeholder in the protocol decleration)
func itemAt(index: Int) -> PageItemType
}

class Person : Pageable {/* ... */}

class People {
var people: [Person]?
}

extension People : Page {

// explicitly satisfies the Page associatedtype requirement.
// this can be done implicitly be the itemAt(index:) method,
// so could be deleted (and annotate the return type of itemAt(index:) as Person)
typealias PageItemType = Person

// the itemAt(index:) method on People now returns a Person
func itemAt(index: Int) -> PageItemType {

// I would advise against force unwrapping here.
// Your people array most likely should be non-optional,
// with an initial value of an empty array
// (do you really need to distinguish between an empty array and no array?)
let person = self.people![index]
return person
}
}

关于您的 PagedCollection 实现 – 因为您的 Page 协议(protocol)中的 PageItemType 关联类型符合 Pageable,我认为不需要 ItemType 通用参数。这可以通过给定 PageType 通用参数的关联类型简单地访问。

举个例子:

class PagedCollection<PageType:Page> {

// PageType's associatedtype, which will conform to Pageable.
// In the case of the PageType generic parameter being People,
// PageType.PageItemType would be of type Person
var foo : PageType.PageItemType

init(foo: PageType.PageItemType) {
self.foo = foo
}
}

// p.foo is of type Person, and is guarenteed to conform to Pageable
let p = PagedCollection<People>(foo: Person())

关于swift - 使类扩展符合通用协议(protocol)功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39539056/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com