创建一个可复制的协议默认初始化器
Create a copyable protocol default initializer
我得到了这个功能:
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?)
}
我想为 class 提供一个默认初始化器:
- 符合
ContentType
- 符合
Copyable
对于上面的代码,我总是在所需的 init 中做同样的事情:调用实现 class 的复制函数。有没有办法在保留此初始化程序的同时省略 classes 中的重复代码?我想到了它添加到协议扩展:
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。有什么办法可以提供调用复制函数的默认初始化程序吗?
I want to provide a default initializer for a class that:
- Conforms to
ContentType
- Conforms to
Copyable
我会假设你的意思是这样回答这个问题:
- 您想提供
init(existingContentType: T, newContentTypeId: String?)
初始值设定项的 默认实现 ,如 ContentType
、if[=86= 中的蓝图] 符合ContentType
的类型也符合Copyable
.
让我们先看看您的 Copyable
协议。这可能是由于在您的问题中遗漏了 details/use 大小写,但我在这里看不到相关类型 T
的需要,因为协议基本上是 blueprints/promises "the class
type conforming to Copyable
, say e.g. TheClassType
, will provide an implementation of the static
copy(from: TheClassType, to: TheClassType)
function" — 其中符合类型 (TheClassType
) 只是 Self
。即:
protocol Copyable: class {
static func copy(from: Self, to: Self)
}
同样适用于 ContentType
:这里是否需要 associatedType
,或者给定具体类型的 ContentType
只是类型本身;即 Self
?在继续之前,让我们去掉与您的问题无关的部分:
protocol ContentType {
var contentTypeId: String? { get }
}
现在,在任何初始化器复制(不是赋值 - 我们正在处理引用类型)任何东西 到 self
之前(例如 [=36 的值类型成员=]), self
必须已经初始化(或分配给)。因此,允许为 ContentType
的 init(existingContentType: Self, newContentTypeId: String?)
初始值设定项提供默认实现(在符合 Copyable
的情况下;Self
是 class
类型)——其中实现旨在利用 copyable
的蓝图 copy(from: Self, to: Self)
——符合 ContentType
的类型必须知道在 之前 初始化自身的方法复制步骤。即,ContentType
需要在调用 copy(from:to)
方法之前设计一些可用于在 "copying initializer" 中初始化 self
的初始化器。让我们简单地绘制蓝图 init()
:
protocol ContentType {
var contentTypeId: String? { get set }
init()
}
现在,由于 ContentType
蓝图 contentTypeId
成员,并且复制初始化程序包含 newContentTypeId
参数,因此提供默认实现的初始化程序 [=52] 可能是明智的=] 作为唯一的参数;即 init(contentTypeId: String?)
:
extension ContentType {
init(contentTypeId: String?) {
self.init()
self.contentTypeId = contentTypeId
}
}
有了这个,我们可以提供默认实现的 init(existingContentType: Self, newContentTypeId: String?)
初始化器作为对 ContentType
的约束扩展,基于 Self
与 Copyable
的一致性:
extension ContentType where Self: Copyable {
init(existingContentType: Self, newContentTypeId: String?) {
self.init(contentTypeId: newContentTypeId)
Self.copy(from: existingContentType, to: self)
}
}
示例
综合以上:
protocol Copyable: class {
static func copy(from: Self, to: Self)
}
protocol ContentType {
var contentTypeId: String? { get set }
init()
}
extension ContentType {
init(contentTypeId: String?) {
self.init()
self.contentTypeId = contentTypeId
}
}
extension ContentType where Self: Copyable {
init(existingContentType: Self, newContentTypeId: String?) {
self.init(contentTypeId: newContentTypeId)
Self.copy(from: existingContentType, to: self)
}
}
示例:
// Copyable content type
final class Foo: ContentType, Copyable {
// Note that since all stored properties have initial values,
// the compiler provides a synthesized initializer for init().
var contentTypeId: String?
var data = 0
static func copy(from: Foo, to: Foo) {
to.data = from.data
}
}
let foo1 = Foo(contentTypeId: "foo1")
foo1.data = 42
let foo2 = Foo(existingContentType: foo1, newContentTypeId: "foo2")
print(foo1.contentTypeId ?? "None", foo1.data) // foo1 42
print(foo2.contentTypeId ?? "None", foo2.data) // foo2 42
// Non-copyable content type
final class Bar: ContentType {
var contentTypeId: String?
} // Bar has no access to
// init(existingContentType: Self, newContentTypeId: String?)
我得到了这个功能:
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?)
}
我想为 class 提供一个默认初始化器:
- 符合
ContentType
- 符合
Copyable
对于上面的代码,我总是在所需的 init 中做同样的事情:调用实现 class 的复制函数。有没有办法在保留此初始化程序的同时省略 classes 中的重复代码?我想到了它添加到协议扩展:
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。有什么办法可以提供调用复制函数的默认初始化程序吗?
I want to provide a default initializer for a class that:
- Conforms to
ContentType
- Conforms to
Copyable
我会假设你的意思是这样回答这个问题:
- 您想提供
init(existingContentType: T, newContentTypeId: String?)
初始值设定项的 默认实现 ,如ContentType
、if[=86= 中的蓝图] 符合ContentType
的类型也符合Copyable
.
让我们先看看您的 Copyable
协议。这可能是由于在您的问题中遗漏了 details/use 大小写,但我在这里看不到相关类型 T
的需要,因为协议基本上是 blueprints/promises "the class
type conforming to Copyable
, say e.g. TheClassType
, will provide an implementation of the static
copy(from: TheClassType, to: TheClassType)
function" — 其中符合类型 (TheClassType
) 只是 Self
。即:
protocol Copyable: class {
static func copy(from: Self, to: Self)
}
同样适用于 ContentType
:这里是否需要 associatedType
,或者给定具体类型的 ContentType
只是类型本身;即 Self
?在继续之前,让我们去掉与您的问题无关的部分:
protocol ContentType {
var contentTypeId: String? { get }
}
现在,在任何初始化器复制(不是赋值 - 我们正在处理引用类型)任何东西 到 self
之前(例如 [=36 的值类型成员=]), self
必须已经初始化(或分配给)。因此,允许为 ContentType
的 init(existingContentType: Self, newContentTypeId: String?)
初始值设定项提供默认实现(在符合 Copyable
的情况下;Self
是 class
类型)——其中实现旨在利用 copyable
的蓝图 copy(from: Self, to: Self)
——符合 ContentType
的类型必须知道在 之前 初始化自身的方法复制步骤。即,ContentType
需要在调用 copy(from:to)
方法之前设计一些可用于在 "copying initializer" 中初始化 self
的初始化器。让我们简单地绘制蓝图 init()
:
protocol ContentType {
var contentTypeId: String? { get set }
init()
}
现在,由于 ContentType
蓝图 contentTypeId
成员,并且复制初始化程序包含 newContentTypeId
参数,因此提供默认实现的初始化程序 [=52] 可能是明智的=] 作为唯一的参数;即 init(contentTypeId: String?)
:
extension ContentType {
init(contentTypeId: String?) {
self.init()
self.contentTypeId = contentTypeId
}
}
有了这个,我们可以提供默认实现的 init(existingContentType: Self, newContentTypeId: String?)
初始化器作为对 ContentType
的约束扩展,基于 Self
与 Copyable
的一致性:
extension ContentType where Self: Copyable {
init(existingContentType: Self, newContentTypeId: String?) {
self.init(contentTypeId: newContentTypeId)
Self.copy(from: existingContentType, to: self)
}
}
示例
综合以上:
protocol Copyable: class {
static func copy(from: Self, to: Self)
}
protocol ContentType {
var contentTypeId: String? { get set }
init()
}
extension ContentType {
init(contentTypeId: String?) {
self.init()
self.contentTypeId = contentTypeId
}
}
extension ContentType where Self: Copyable {
init(existingContentType: Self, newContentTypeId: String?) {
self.init(contentTypeId: newContentTypeId)
Self.copy(from: existingContentType, to: self)
}
}
示例:
// Copyable content type
final class Foo: ContentType, Copyable {
// Note that since all stored properties have initial values,
// the compiler provides a synthesized initializer for init().
var contentTypeId: String?
var data = 0
static func copy(from: Foo, to: Foo) {
to.data = from.data
}
}
let foo1 = Foo(contentTypeId: "foo1")
foo1.data = 42
let foo2 = Foo(existingContentType: foo1, newContentTypeId: "foo2")
print(foo1.contentTypeId ?? "None", foo1.data) // foo1 42
print(foo2.contentTypeId ?? "None", foo2.data) // foo2 42
// Non-copyable content type
final class Bar: ContentType {
var contentTypeId: String?
} // Bar has no access to
// init(existingContentType: Self, newContentTypeId: String?)