Swift5:如何在声明变量时指定符合协议的泛型类型
Swift 5: how to specify a generic type conforming to protocol when declaring a variable
我在 Swift 5. 我有协议:
protocol Pipe {
associatedtype T
func await() -> Void
func yield( to: Any, with listener: Selector ) -> Void
}
我想在代码中的某处引用此协议的一个实例。也就是说,我想要 foo : 或实现 Pipe 的通用类型 T 的变量。根据此文档:https://docs.swift.org/swift-book/ReferenceManual/GenericParametersAndArguments.html
我试过写:
var imageSource: <Pipe T>
以及所述符号的任何排列,即 imageSource: 但所有情况下的语法都是错误的。
其实T符合两个协议,Renderable和Pipe,所以我很想:
var imageSource: <Pipe, Renderable T>
从语法上讲这是乱码,但从语义上讲这并不是一个罕见的用例。
__________________ 在给出两个答案后编辑 __________
我尝试为此 post 简化 Pipe
协议,但现在我意识到我简化了太多。在我的代码库中它是
protocol Pipe {
associatedtype T
func await() -> Void
func yield( to: Any, with listener: Selector ) -> Void
func batch() -> [T]
}
这就是为什么那里有一个 T。但这并不重要,如果我能够在上面写下我想要的,我可以删除batch() -> [T]
。
这称为广义存在主义,在 Swift 中不可用。具有关联类型的协议描述其他类型;它本身不是类型,不能是变量的类型,也不能放入集合中。
此特定协议没有多大意义,因为您不会在任何地方使用 T
。但是您需要做的是将其拉入包含类型:
struct Something<Source> where Source: Pipe & Renderable {
var imageSource: Source
}
不过,我怀疑您真的想以不同的方式重新设计它。这看起来像是一种相当常见的协议滥用。您可能希望 Pipe
和 Renderer
类型是结构(甚至只是函数)。在不知道调用代码是什么样子的情况下,我不能准确地说出你将如何设计它。
如果您删除 T
(此处未使用),Max 的回答将解决此问题。没有关联类型的协议具有隐式存在类型,因此您可以将它们视为 "normal" 类型(将它们分配给变量或将它们放入集合中)。
当您希望您的协议适用于多种类型时,可以使用关联类型,想想一个 Container
协议可能有多个方法都处理一个包含的类型。
但是你的协议不是那个,它不需要知道任何其他类型来指定必要的行为,所以去掉关联的类型。
protocol Pipe {
func await() -> Void
func yield( to: Any, with listener: Selector ) -> Void
}
class Foo {
var imageSource: Pipe & Renderable
}
我在 Swift 5. 我有协议:
protocol Pipe {
associatedtype T
func await() -> Void
func yield( to: Any, with listener: Selector ) -> Void
}
我想在代码中的某处引用此协议的一个实例。也就是说,我想要 foo : 或实现 Pipe 的通用类型 T 的变量。根据此文档:https://docs.swift.org/swift-book/ReferenceManual/GenericParametersAndArguments.html
我试过写:
var imageSource: <Pipe T>
以及所述符号的任何排列,即 imageSource: 但所有情况下的语法都是错误的。
其实T符合两个协议,Renderable和Pipe,所以我很想:
var imageSource: <Pipe, Renderable T>
从语法上讲这是乱码,但从语义上讲这并不是一个罕见的用例。
__________________ 在给出两个答案后编辑 __________
我尝试为此 post 简化 Pipe
协议,但现在我意识到我简化了太多。在我的代码库中它是
protocol Pipe {
associatedtype T
func await() -> Void
func yield( to: Any, with listener: Selector ) -> Void
func batch() -> [T]
}
这就是为什么那里有一个 T。但这并不重要,如果我能够在上面写下我想要的,我可以删除batch() -> [T]
。
这称为广义存在主义,在 Swift 中不可用。具有关联类型的协议描述其他类型;它本身不是类型,不能是变量的类型,也不能放入集合中。
此特定协议没有多大意义,因为您不会在任何地方使用 T
。但是您需要做的是将其拉入包含类型:
struct Something<Source> where Source: Pipe & Renderable {
var imageSource: Source
}
不过,我怀疑您真的想以不同的方式重新设计它。这看起来像是一种相当常见的协议滥用。您可能希望 Pipe
和 Renderer
类型是结构(甚至只是函数)。在不知道调用代码是什么样子的情况下,我不能准确地说出你将如何设计它。
如果您删除 T
(此处未使用),Max 的回答将解决此问题。没有关联类型的协议具有隐式存在类型,因此您可以将它们视为 "normal" 类型(将它们分配给变量或将它们放入集合中)。
当您希望您的协议适用于多种类型时,可以使用关联类型,想想一个 Container
协议可能有多个方法都处理一个包含的类型。
但是你的协议不是那个,它不需要知道任何其他类型来指定必要的行为,所以去掉关联的类型。
protocol Pipe {
func await() -> Void
func yield( to: Any, with listener: Selector ) -> Void
}
class Foo {
var imageSource: Pipe & Renderable
}