swift - 创建一个可复制的协议默认初始化器
问题描述
我得到了这个功能:
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 中做同样的事情:调用实现类的复制函数。有没有办法在保留这个初始化程序的同时省略跨类的重复代码?我想把它添加到协议扩展中:
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 中输入什么,我不能使用相关类型。有什么方法可以提供调用复制函数的默认初始化程序?
解决方案
我想为一个类提供一个默认初始化程序:
- 符合
ContentType
- 符合
Copyable
我将尝试回答这个问题,假设您的意思是:
- 如果符合的类型也符合.
init(existingContentType: T, newContentTypeId: String?)
_ContentType
_ContentType
Copyable
让我们先看看你的Copyable
协议。这可能是由于您的问题中省略了细节/用例,但我在这里看不到相关类型的需要T
,因为协议基本上蓝图/承诺“class
符合的类型Copyable
,例如TheClassType
,将提供static
copy(from: TheClassType, to: TheClassType)
函数” ——其中符合类型 ( TheClassType
) 只是Self
. IE:
protocol Copyable: class {
static func copy(from: Self, to: Self)
}
这同样适用于ContentType
:这里是否需要一个associatedType
,或者ContentType
给定的具体类型只是类型本身;即Self
?在继续之前,让我们去掉与您的问题无关的部分:
protocol ContentType {
var contentTypeId: String? { get }
}
现在,在任何初始化程序复制(而不是分配 - 我们正在处理引用类型)任何东西到 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
基于 to 一致性的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?)
推荐阅读
- electron - 电子反应样板:window.electron 不存在错误
- uwp - UWP 中的 DataGrid 层次结构
- python - 辞职后变量不显示
- node.js - ReferenceError:未定义配置(反应:ms server sql,node.js)
- javascript - 在另一个函数中使用来自异步函数的返回数据
- javascript - withObservables 和 await
- python - 您可以创建自定义 AWS Kinesis 错误输出类型吗?
- sql - 根据具有重复值的 2 列获取唯一行
- node.js - 使自定义标头请求成为必需
- json - 使用 vb.net 反序列化多级 JSON 字符串