创建一个可复制的协议默认初始化程序

时间:2018-07-07 11:15:56

标签: swift protocols type-alias associated-types

我有这个功能:

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。有什么方法可以提供调用复制功能的默认初始化程序?

1 个答案:

答案 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}}初始化程序提供默认实现(如果符合selfselfself类型),其中实现的目的是利用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

有了这一点,我们可以基于contentTypeIdnewContentTypeId的一致性,提供默认实现的contentTypeId初始化程序,作为对init(contentTypeId: String?)的约束扩展:

extension ContentType {
    init(contentTypeId: String?) {
        self.init()
        self.contentTypeId = contentTypeId
    }
}

示例

将以上内容放在一起:

init(existingContentType: Self, newContentTypeId: String?)

示例:

ContentType