多个协议扩展中的功能不明确?
Ambiguous functions in multiple protocol extensions?
我有多个具有相同函数名称的协议。某些协议具有关联类型,我无法像在非通用协议中那样弄清楚如何调用这些函数。我收到错误:Protocol 'MyProtocol1' can only be used as a generic contraint because it has Self or associated type requirements
这是我正在尝试做的事情:
protocol Serviceable {
associatedtype DataType
func get(handler: ([DataType] -> Void)?)
}
struct PostService: Serviceable {
func get(handler: ([String] -> Void)? = nil) {
print("Do something...")
}
}
protocol MyProtocol1: class {
associatedtype ServiceType: Serviceable
var service: ServiceType { get }
}
extension MyProtocol1 {
func didLoad(delegate: Self) {
print("MyProtocol1.didLoad()")
}
}
protocol MyProtocol2: class {
}
extension MyProtocol2 {
func didLoad(delegate: MyProtocol2) {
print("MyProtocol2.didLoad()")
}
}
class MyViewController: UIViewController, MyProtocol1, MyProtocol2 {
let service = PostService()
override func viewDidLoad() {
super.viewDidLoad()
didLoad(self as MyProtocol1) // Error here: Protocol 'MyProtocol1' can only be used as a generic contraint because it has Self or associated type requirements
didLoad(self as MyProtocol2)
}
}
如何从通用协议扩展中专门调用该函数?
通过将协议变成通用协议(见下文)或为这些协议创建一个 type eraser 很容易实现,但这非常强烈地表明你有设计问题,你应该重新设计你的类 and/or 个扩展名。像这样的碰撞强烈表明 MyStruct
本身做了太多事情,因为它被 MyProtocol1
和 MyProtocol2
拉向多个方向。这里应该有两个对象。 (组合而不是继承。)
class MyStruct: MyProtocol1, MyProtocol2 {
let service = PostService()
func prot1Load<T: MyProtocol1>(t: T) {
t.didLoad()
}
func prot2Load<T: MyProtocol2>(t: T) {
t.didLoad()
}
init() {
prot1Load(self)
prot2Load(self)
}
}
对于您在评论中的特定示例,我会使用组合而不是继承。您将协议视为多重继承,这几乎是不对的。而是用符合协议的东西组成。
protocol LoadProviding {
func load()
}
struct MyLoader1: LoadProviding {
func load() {
print("MyLoader1.didLoad()")
}
}
struct MyLoader2: LoadProviding {
func load() {
print("MyLoader2.didLoad()")
}
}
protocol Loader {
var loaders: [LoadProviding] { get }
}
extension Loader {
func loadAll() {
for loader in loaders {
loader.load()
}
}
}
class MyStruct: Loader {
let service = PostService()
let loaders: [LoadProviding] = [MyLoader1(), MyLoader2()]
init() {
loadAll()
}
}
当然,您不必 LoadProviding
是一个完整的结构。如果这就是您所需要的,它可能只是一个函数:
typealias LoadProviding = () -> Void
func myLoader1() {
print("MyLoader1.didLoad()")
}
func myLoader2() {
print("MyLoader2.didLoad()")
}
protocol Loader {
var loaders: [LoadProviding] { get }
}
extension Loader {
func loadAll() {
for loader in loaders {
loader()
}
}
}
class MyStruct: Loader {
let service = PostService()
let loaders: [LoadProviding] = [myLoader1, myLoader2]
init() {
loadAll()
}
}
如果您有时间浏览有关该主题的视频,您可能会对来自 dotSwift 的 Beyond Crusty: Real World Protocols 演讲感兴趣。这是关于这个和类似的问题。
我有多个具有相同函数名称的协议。某些协议具有关联类型,我无法像在非通用协议中那样弄清楚如何调用这些函数。我收到错误:Protocol 'MyProtocol1' can only be used as a generic contraint because it has Self or associated type requirements
这是我正在尝试做的事情:
protocol Serviceable {
associatedtype DataType
func get(handler: ([DataType] -> Void)?)
}
struct PostService: Serviceable {
func get(handler: ([String] -> Void)? = nil) {
print("Do something...")
}
}
protocol MyProtocol1: class {
associatedtype ServiceType: Serviceable
var service: ServiceType { get }
}
extension MyProtocol1 {
func didLoad(delegate: Self) {
print("MyProtocol1.didLoad()")
}
}
protocol MyProtocol2: class {
}
extension MyProtocol2 {
func didLoad(delegate: MyProtocol2) {
print("MyProtocol2.didLoad()")
}
}
class MyViewController: UIViewController, MyProtocol1, MyProtocol2 {
let service = PostService()
override func viewDidLoad() {
super.viewDidLoad()
didLoad(self as MyProtocol1) // Error here: Protocol 'MyProtocol1' can only be used as a generic contraint because it has Self or associated type requirements
didLoad(self as MyProtocol2)
}
}
如何从通用协议扩展中专门调用该函数?
通过将协议变成通用协议(见下文)或为这些协议创建一个 type eraser 很容易实现,但这非常强烈地表明你有设计问题,你应该重新设计你的类 and/or 个扩展名。像这样的碰撞强烈表明 MyStruct
本身做了太多事情,因为它被 MyProtocol1
和 MyProtocol2
拉向多个方向。这里应该有两个对象。 (组合而不是继承。)
class MyStruct: MyProtocol1, MyProtocol2 {
let service = PostService()
func prot1Load<T: MyProtocol1>(t: T) {
t.didLoad()
}
func prot2Load<T: MyProtocol2>(t: T) {
t.didLoad()
}
init() {
prot1Load(self)
prot2Load(self)
}
}
对于您在评论中的特定示例,我会使用组合而不是继承。您将协议视为多重继承,这几乎是不对的。而是用符合协议的东西组成。
protocol LoadProviding {
func load()
}
struct MyLoader1: LoadProviding {
func load() {
print("MyLoader1.didLoad()")
}
}
struct MyLoader2: LoadProviding {
func load() {
print("MyLoader2.didLoad()")
}
}
protocol Loader {
var loaders: [LoadProviding] { get }
}
extension Loader {
func loadAll() {
for loader in loaders {
loader.load()
}
}
}
class MyStruct: Loader {
let service = PostService()
let loaders: [LoadProviding] = [MyLoader1(), MyLoader2()]
init() {
loadAll()
}
}
当然,您不必 LoadProviding
是一个完整的结构。如果这就是您所需要的,它可能只是一个函数:
typealias LoadProviding = () -> Void
func myLoader1() {
print("MyLoader1.didLoad()")
}
func myLoader2() {
print("MyLoader2.didLoad()")
}
protocol Loader {
var loaders: [LoadProviding] { get }
}
extension Loader {
func loadAll() {
for loader in loaders {
loader()
}
}
}
class MyStruct: Loader {
let service = PostService()
let loaders: [LoadProviding] = [myLoader1, myLoader2]
init() {
loadAll()
}
}
如果您有时间浏览有关该主题的视频,您可能会对来自 dotSwift 的 Beyond Crusty: Real World Protocols 演讲感兴趣。这是关于这个和类似的问题。