Swift:类型符合 Equatable 的泛型数组

标签 swift generics types protocols equatable

在 Swift 中,如何定义类型符合 Equatable 的泛型数组?

例子:

struct File<T: Equatable> {
    public var lines: [T]
    private var lineCursor = 0
    public var currentLine: T {
        get { return lines[lineCursor] }
        set { lineCursor = lines.index(where: { $0 == newValue }) ?? 0 }
    }
}

struct Folder {
    public var files: [File]? // compile time error
}

→ 对泛型类型"file"的引用需要 <…> 中的参数

……到目前为止我试过:

[File<Any>]

→ 类型“Any”不符合协议(protocol)“Equatable”


[File<Any: Equatable>]

→ 一行中连续的声明必须用';'分隔


[File<Any, Equatable>]

→ 通用类型"file"特化了太多类型参数(得到 2 个,但预期为 1 个)


[File<Any & Equatable>]

→ 不支持使用“Equatable”作为符合协议(protocol)“Equatable”的具体类型


[File<(Any: Equatable)>]

→ 无法创建带有元素标签的单元素元组


[File<(Any, Equatable)>]

→ 类型“(Any, Equatable)”不符合协议(protocol)“Equatable”


[File<(Any & Equatable)>]

→ 不支持使用“Equatable”作为符合协议(protocol)“Equatable”的具体类型


[File<[Any: Equatable]>]

→ 'File' 要求 'Equatable' 符合 'Equatable'


[File<[Any, Equatable]>]

→ 一行中连续的声明必须用';'分隔


[File<[Any & Equatable]>]

→ 'File' 要求 'Equatable' 符合 'Equatable'


正确的语法是什么?


[编辑] 简化示例


[编辑] 更新示例:

class File<T: Equatable> {
    var lines = [T]()
    var lineCursor: Int = 0
    var currentLine: T {
        get { return lines[lineCursor] }
        set { lineCursor = lines.index(where: { $0 == newValue }) ?? 0 }
    }
    var visible = true
}

class Folder {
    var files = [File]() // Generic parameter 'Type' could not be inferred; I want this to be a mixed array
    func currentLinesFromVisibleFiles() -> String {
        return files.filter({ $0.visible }).map({ String(describing: $0.currentLine) }).joined(separator: "/")
    }
}

var stringFile = File<String>()
stringFile.lines = ["strong", "string", "a", "b", "c"]
stringFile.currentLine = "string"
stringFile.visible = true

var intFile = File<Int>()
intFile.lines = [6, 12, 0, 489]
intFile.currentLine = 489
intFile.visible = true

var doubleFile = File<Double>()
doubleFile.lines = [92.12, 4.9753, 1.6]
doubleFile.currentLine = 92.12
doubleFile.visible = false

var boolFile = File<Bool>()
boolFile.lines = [true, false]
boolFile.currentLine = true
boolFile.visible = true

var folder = Folder()
folder.files = [stringFile, intFile, doubleFile, boolFile]

let output = folder.currentLinesFromVisibleFiles() // I want: "string/489/true"

最佳答案

您必须指定 T 的类型[File<T>]? 上的参数为了让编译器通过,请注意您正在尝试创建一个同构数组,一旦您指定 T作为最终类型,您不能在 file 上混合类型,即你不能混合 File<Int>File<String> .如果您需要 Equatable一致性计算currentLine您可以使用符合条件的动态添加属性是否天气 T是平等的,因为:

protocol HasCurrentLine{
    associatedtype LineType
    var currentLine: LineType { set get }
}

struct File<T> where T:Any {
    public var lines: [T]
    var lineCursor = 0
}

extension File : HasCurrentLine where T : Equatable{
    typealias LineType = T
    var currentLine: T {
        get { return lines[lineCursor] }
        set { lineCursor = lines.index(where: { $0 == newValue }) ?? 0 
    }
  }
}
struct Folder {
    public var files: [File<Any>]?
}

这样你就可以在T时计算行数是Equatable

关于Swift:类型符合 Equatable 的泛型数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50319072/

相关文章:

ios - SWIFT 删除 subview

ios - 我在上传时不断收到错误 "This action could not be completed. Try again. (-22421)"

c# - 如何在 C# 中实现通用缓存管理器

c# - 可变长度参数 c#

ios - 使用 Swift 发送到实例的无法识别的选择器

swift - 如何将具有自定义指定初始化程序的 UISegmentedControl 子类化?

java - 使用 Dagger 注入(inject)通配符类型

powershell - PowerShell 中的强类型引用?

scala - 无法覆盖具有非 volatile 上限的类型

types - 什么时候仅在运行时才知道类型?