【问题标题】:Inherit array with own type and stored properties in Swift在 Swift 中继承具有自己类型和存储属性的数组
【发布时间】:2022-01-07 23:54:52
【问题描述】:

通常我有一个包含MemoryComponent 类的数组(所以[MemoryComponent])。我想将其重构为一个自定义数组类,它的元素类型为MemoryComponent,并包含程序可以使用的存储属性。

我尝试创建一个扩展,但它不允许存储属性:

extension Array where Element: MemoryComponent {
    // ... no stored properties due to extension
}

我还尝试为数组创建另一个类:

class StorageArray: Array<MemoryComponent> {
    // ... stored properties are possible
    // but there's an error because of this:
    // error: inheritance from non-protocol, non-class type 'Array<MemoryComponent>'
}

如何有效地从 [MemoryComponent] 创建继承以包含存储的属性?

【问题讨论】:

  • 使用组合而不是继承,创建一个将数组作为(私有)属性的新类,然后添加其他属性和函数来访问/修改数组。如果你不需要对它进行那种控制,你也可以让数组公开。
  • @JoakimDanielson - 这是一种可能性,尽管在这种情况下(直接)不提供内置数组方法
  • 如果您想包含自己的存储属性,我认为您没有那么多其他选择
  • 是否有类似数组的协议来创建类?
  • 是的,请查看 Array 的文档,看看它符合什么。

标签: arrays swift inheritance


【解决方案1】:

为您的案例使用组合可能会更好。

...但是如果您真正想要的是自定义类型的Array,那么实际上有一个奇怪且不推荐的选项来破解它。

您不能从Array 继承,因为它是struct。但是你可以实现Collection 协议。

struct MemoryComponent {}

struct MemoryComponentsArray: Collection {
    
    // typealias all associatedTypes of `Collection` protocol
    typealias Element = MemoryComponent
    typealias Index = Array<Element>.Index
    typealias SubSequence = Array<Element>.SubSequence
    typealias Iterator = Array<Element>.Iterator
    typealias Indices = Array<Element>.Indices
    
    /// Your real data storage
    private let internalArray: Array<Element>
    
    /**
     Create any custom initializers you need
     */
    init(_ arrayLiteral: [Element]) {
        self.internalArray = arrayLiteral
    }
    
    // Implement `Collection` protocol core stuff
    // By referencing to internal array
    
    var startIndex: Index { internalArray.startIndex }
    var endIndex: Index { internalArray.endIndex }
    func makeIterator() -> Iterator { internalArray.makeIterator() }
    subscript(position: Index) -> Element { internalArray[position] }
    subscript(bounds: Range<Index>) -> SubSequence { internalArray[bounds] }
    var indices: Indices { internalArray.indices }
    var isEmpty: Bool { internalArray.isEmpty }
    var count: Int { internalArray.count }
    func index(_ i: Index, offsetBy distance: Int) -> Index {
        internalArray.index(i, offsetBy: distance)
    }
    func index(_ i: Index, offsetBy distance: Int, limitedBy limit: Index) -> Index? {
        internalArray.index(i, offsetBy: distance, limitedBy: limit)
    }
    func distance(from start: Index, to end: Index) -> Int {
        internalArray.distance(from: start, to: end)
    }
    func index(after i: Index) -> Index {
        internalArray.index(after: i)
    }
    func formIndex(after i: inout Index) {
        internalArray.formIndex(after: &i)
    }
}

【讨论】:

  • 此时,使用组合策略可能比重新实现大多数数组方法更好
  • @Smally 是的,没错。 Array 的大部分功能已经在 Collection 协议的扩展中实现。取决于您需要什么 Array 方法。我在上面发布的内容是您有义务实施的所有内容。其他一切都是可选的。
猜你喜欢
  • 2023-04-10
  • 2017-02-23
  • 2016-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-18
相关资源
最近更新 更多