好的,我有一个协议MenuEntry,我想用它填充一个TableView:
protocol MenuEntry {
static var title: String { get }
static func entrySelected(_ menuController: MenuController)
}我想在不同的地方实现这个协议,让项目本身来决定该做什么。它可能是实现协议的UIViewController,也可能是简单的结构,然后调用菜单本身上的函数:
struct SomeEntry: MenuEntry {
static var title: String { return "Some Entry" }
static func entrySelected(_ menuController: MenuController) {
menuController.doSomething()
}
}现在,我希望构建MenuControllers数据源,但不实际实例化条目,因为尤其是在填充MenuControllers数据源时,视图控制器不一定可用。这就是为什么我在MenuEntry中使用静态var/func。目前,我只需这样做就可以填充数据源:
let dataSource: [MenuEntry.Type] = [SomeEntry.self]而且看起来效果很好。我可以获取条目并调用相应的函数:
dataSource.first?.title //Gives me "Some Entry"现在出现了棘手的部分。我认为我可以非常聪明地创建一个协议扩展,其中我引用了实现该协议的所有类型,如下所示:
extension MenuEntry {
static var someEntry: MenuEntry.Type { return SomeEntry.self }
//...
}然后再通过MenuEntry.someEntry使用它们。但是,在someEntry上访问MenuEntry会给我一个错误:
error: static member 'someEntry' cannot be used on protocol metatype 'MenuEntry.Protocol',所以我的问题是:我错过了什么?我只是试图以一种非故意的方式滥用语言,还是我只是做错了什么?
溶液
从下面被接受的答案来看,我现在是如何做事的。首先,我们需要前面提到的结构(我想不需要一个类):
struct MenuEntries {}然后,在实现MenuEntry协议的地方,我还扩展了这个结构,并添加了如下条目:
struct SomeEntry: MenuEntry {
static var title: String { return "Some Entry" }
static func entrySelected(_ menuController: MenuController) {
menuController.doSomething()
}
}
extension MenuEntries {
static var someEntry: MenuEntry.Type { return SomeEntry.self }
}最后一件事是像这样创建我的数据源:
let dataSource: [MenuEntry.Type] = [MenuEntries.someEntry, ...]好的,现在我在一个地方有一张所有菜单条目的列表。缺点是我必须记住每次都要扩展MenuEntries。除了有一些神奇的方法来扩展一个结构的条件基,我不知道。但我想这只是太过了,根本不可能。
发布于 2017-05-20 04:27:01
协议定义了适合特定任务或功能的方法、属性和其他需求的蓝图。然后,类、结构或枚举可以采用该协议来提供这些需求的实际实现。“
您的扩展试图在协议中直接实现功能,但这是不允许的;只有采用该协议的类、结构或枚举才能提供功能。
您可以定义一个返回菜单类的类:
class MenuFactory {
static var someEntry: MenuEntry.type { return SomeEntry.self }
}https://stackoverflow.com/questions/44080955
复制相似问题