我有一个Swift协议,它定义了如下方法:
protocol MyProtocol {
class func retrieve(id:String) -> Self?
}
我有几个不同的类符合这个协议:
class MyClass1 : MyProtocol { ... }
class MyClass2 : MyProtocol { ... }
class MyClass3 : MyProtocol { ... }
每个子类中 retrieve
方法的实现几乎相同 . 我想将这些函数的通用实现拉入符合协议的共享超类:
class MyBaseClass : MyProtocol
{
class func retrieve(id:String) -> MyBaseClass?
}
class MyClass1 : MyBaseClass { ... }
class MyClass2 : MyBaseClass { ... }
class MyClass3 : MyBaseClass { ... }
这种方法的问题是我的协议将 retrieve
方法的返回类型定义为类型 Self
,这是我最终想要的 . 但是,因此我无法以这种方式在基类中实现 retrieve
,因为它会导致 MyClass1
, MyClass2
和 MyClass3
的编译器错误 . 这些类中的每一个都必须符合它们从 MyBaseClass
继承的协议 . 但是因为该方法是使用 MyBaseClass
的返回类型实现的,并且协议要求它是 MyClass1
,所以它表示我的类不符合协议 .
我想知道是否有一种干净的方法来实现一个协议方法,该方法在基类中的一个或多个方法中引用 Self
类型 . 我当然可以在基类中实现一个不同命名的方法,然后让每个子类通过调用它的超类来实现协议's method to do the work, but that doesn' t对我来说似乎特别优雅 .
我在这里缺少一种更简单的方法吗?
3 回答
这应该工作:
required init() { }
是必要的,以确保从MyBaseClass
派生的任何子类具有init()
初始化程序 .请注意,此代码崩溃了Swift Playground . 我不知道为什么 . 所以试试真实的项目 .
不知道你想通过你的例子在这里完成什么,所以这是一个可能的解决方案:
背后的理由
声明是这样的,只有引用类型可以是扩展名 . 你可能不会对你的课程进行处理 .
我已经将@rintaro的答案标记为正确的答案,因为它确实回答了我提出的问题 . 但是,我发现这个解决方案太有限了,所以我发布了我发现在这里遇到遇到这个问题的其他人的替代答案 .
上一个答案的限制是它只有在
Self
(在我的例子中为MyClass1
,MyClass2
或MyClass3
)表示的类型在协议中使用或作为类方法的返回类型时才有效 . 所以,当我有这个方法一切都按照我的希望运作 . 但是,当我解决这个问题时,我意识到这个方法现在需要是异步的,不能直接返回结果 . 所以我用类方法尝试了这个:
我可以将此方法放入
MyProtocol
但是当我尝试在MyBaseClass
中实现时,我得到以下编译器错误:所以我真的不能使用这种方法,除非
Self
引用的类型以非常具体的方式使用 .经过一些实验和大量的SO研究,我终于能够使用泛型来更好地工作 . 我在我的协议中定义了如下方法:
然后在我的基类中,我执行以下操作:
当我想要检索
MyClass1
类型的实例时,我执行以下操作:通过此实现,
success
的函数类型告诉编译器在MyBaseClass
的retrieve
实现中应该为T
应用什么类型 .