我有这个功能:
public protocol ContentType {
associatedtype T
static var allTypes: [T] { get }
static func getContentType(contentTypeId: String) -> T
var contentTypeId: String? { get }
}
public protocol Copyable: class {
associatedtype T
static func copy(old: T, new: T)
}
public protocol CopyableContentType: class {
associatedtype T
init(existingContentType: T, newContentTypeId: String?)
}
我想为以下类提供默认的初始化程序:
ContentType
Copyable
使用上面的代码,我总是在所需的init中执行相同的操作:调用实现类的copy函数。有什么办法可以在保留此初始值设定项的情况下在各个类之间省略此重复的代码?我想到了将其添加到协议扩展中:
public extension CopyableContentType where Self: ContentType & Copyable {
typealias T = Self // So wrong but I have no idea what to put here
// T should be the same T as the T usud in ContentType and Copyable
init(existingContentType: T, newContentTypeId: String?) {
Self.copy(old: existingContentType, new: self)
}
}
但这会导致一些错误。我不知道要在typealias中添加什么,并且我不能使用associatedtypes。有什么方法可以提供调用复制功能的默认初始化程序?
答案 0 :(得分:2)
我想为以下类提供默认的初始化程序:
- 符合
ContentType
- 符合
Copyable
假设您的意思是,我将尝试回答此问题:
init(existingContentType: T, newContentTypeId: String?)
初始化程序的默认实现,如ContentType
的蓝图所示, if 类型符合{{1 }}也符合ContentType
。我们首先来看看您的Copyable
协议。这可能是由于您的问题中省略了详细信息/用例,但我在这里看不到相关类型Copyable
的需要,因为该协议基本上是蓝图/承诺了{em>“ {{1} }符合T
的类型,例如class
,将提供Copyable
TheClassType
函数的实现” -其中符合类型({{1} })就是static
。即:
copy(from: TheClassType, to: TheClassType)
TheClassType
同样成立:这里是否需要Self
,还是给定具体类型的protocol Copyable: class {
static func copy(from: Self, to: Self)
}
?即ContentType
?在继续之前,先剥去与您的问题无关的部分:
associatedType
现在,在任何初始化程序复制(不分配-我们正在处理引用类型)之前,将任何内容复制到 ContentType
(例如,Self
的值类型成员),{ {1}}必须已初始化(或分配给)。因此,允许为protocol ContentType {
var contentTypeId: String? { get }
}
的{{1}}初始化程序提供默认实现(如果符合self
; self
是self
类型),其中实现的目的是利用init(existingContentType: Self, newContentTypeId: String?)
的蓝图ContentType
-符合Copyable
的类型必须知道在复制步骤之前 初始化自身的方法。也就是说,Self
需要在调用class
方法之前在“复制初始化程序”中为可初始化copy(from: Self, to: Self)
的一些初始化程序提供蓝图。让我们简单地设计copyable
:
ContentType
现在,由于ContentType
设计了一个self
成员,并且复制初始化程序包含一个copy(from:to)
参数,因此明智的做法是为init()
提供一个默认实现的初始化程序作为其唯一参数;即protocol ContentType {
var contentTypeId: String? { get set }
init()
}
:
ContentType
有了这一点,我们可以基于contentTypeId
与newContentTypeId
的一致性,提供默认实现的contentTypeId
初始化程序,作为对init(contentTypeId: String?)
的约束扩展:
extension ContentType {
init(contentTypeId: String?) {
self.init()
self.contentTypeId = contentTypeId
}
}
将以上内容放在一起:
init(existingContentType: Self, newContentTypeId: String?)
示例:
ContentType