How to subclass an array class in Swift?

♀尐吖头ヾ 提交于 2020-01-01 08:42:00

问题


I am new in Swift. I have a base class:

class foo{}

I want to implement a foo collection class:

class foos: Array<foo>{}

But the compiler is complaining:

inheritance from a non-protocol, non-class type of 'Array'

I have tried other syntax (e.g. [foo] and NSMutableArray<foo>) but none of them passes the compiler check.

This should be simple but I have googled all day and could not figure it out. Does anyone know if it is possible and if it is, the correct syntax?


回答1:


Swift's Array type is a structure, and in Swift, base classes must be actual classes (that is, class Foo) and not structures.

So you cannot do what you are trying to do via inheritance from Array, unfortunately. You could, however, store the array as a field within your class and forward methods to it, possibly implementing any protocols you want to support, et cetera.




回答2:


In Swift, Array is a struct, not a class. To have a class that is an array subclass, you will need to use NSArray, its Objective-C counterpart.

For example,

class Foo: NSArray{}



回答3:


In Swift 2.x you can use a protocol extension.

class Foo : Equatable {}
// you need to provide the Equatable functionality
func ==(leftFoo: Foo, rightFoo: Foo) -> Bool {
    return ObjectIdentifier(leftFoo) == ObjectIdentifier(rightFoo)
}

extension Array where Element : Foo {}

protocol extensions provide "insert points" to extend classes that aren't classes, classes you don't own, etc.




回答4:


Details

  • Xcode 10.1 (10B61)
  • Swift 4.2

Idea

You can create own array using RangeReplaceableCollection protocol.

Sample

import Foundation

struct Arr<T: Equatable>: RangeReplaceableCollection {

    typealias Element = T
    typealias Index = Int
    typealias SubSequence = Arr<T>
    typealias Indices = Range<Int>
    fileprivate var array: Array<T>

    var startIndex: Int { return array.startIndex }
    var endIndex: Int { return array.endIndex }
    var indices: Range<Int> { return array.indices }


    func index(after i: Int) -> Int {
        return array.index(after: i)
    }

    init() { array = [] }

}

// Instance Methods

extension Arr {

    init<S>(_ elements: S) where S : Sequence, Arr.Element == S.Element {
        array = Array<S.Element>(elements)
    }

    init(repeating repeatedValue: Arr.Element, count: Int) {
        array = Array(repeating: repeatedValue, count: count)
    }
}

// Instance Methods

extension Arr {

    public mutating func append(_ newElement: Arr.Element) {
        array.append(newElement)
    }

    public mutating func append<S>(contentsOf newElements: S) where S : Sequence, Arr.Element == S.Element {
        array.append(contentsOf: newElements)
    }

    func filter(_ isIncluded: (Arr.Element) throws -> Bool) rethrows -> Arr {
        let subArray = try array.filter(isIncluded)
        return Arr(subArray)
    }

    public mutating func insert(_ newElement: Arr.Element, at i: Arr.Index) {
        array.insert(newElement, at: i)
    }

    mutating func insert<S>(contentsOf newElements: S, at i: Arr.Index) where S : Collection, Arr.Element == S.Element {
        array.insert(contentsOf: newElements, at: i)
    }

    mutating func popLast() -> Arr.Element? {
        return array.popLast()
    }

    @discardableResult mutating func remove(at i: Arr.Index) -> Arr.Element {
        return array.remove(at: i)
    }

    mutating func removeAll(keepingCapacity keepCapacity: Bool) {
        array.removeAll()
    }

    mutating func removeAll(where shouldBeRemoved: (Arr.Element) throws -> Bool) rethrows {
        try array.removeAll(where: shouldBeRemoved)
    }

    @discardableResult mutating func removeFirst() -> Arr.Element {
        return array.removeFirst()
    }

    mutating func removeFirst(_ k: Int) {
        array.removeFirst(k)
    }
    @discardableResult mutating func removeLast() -> Arr.Element {
        return array.removeLast()
    }

    mutating func removeLast(_ k: Int) {
        array.removeLast(k)
    }

    mutating func removeSubrange(_ bounds: Range<Int>) {
        array.removeSubrange(bounds)
    }

    mutating func replaceSubrange<C, R>(_ subrange: R, with newElements: C) where C : Collection, R : RangeExpression, T == C.Element, Arr<T>.Index == R.Bound {
        array.replaceSubrange(subrange, with: newElements)
    }

    mutating func reserveCapacity(_ n: Int) {
        array.reserveCapacity(n)
    }
}

// Subscripts

extension Arr {

    subscript(bounds: Range<Arr.Index>) -> Arr.SubSequence {
        get { return Arr(array[bounds]) }
    }

    subscript(bounds: Arr.Index) -> Arr.Element {
        get { return array[bounds] }
        set(value) { array[bounds] = value }
    }
}

// Operator Functions

extension Arr {

    static func + <Other>(lhs: Other, rhs: Arr) -> Arr where Other : Sequence, Arr.Element == Other.Element {
        return Arr(lhs + rhs.array)
    }

    static func + <Other>(lhs: Arr, rhs: Other) -> Arr where Other : Sequence, Arr.Element == Other.Element{
         return Arr(lhs.array + rhs)
    }

    static func + <Other>(lhs: Arr, rhs: Other) -> Arr where Other : RangeReplaceableCollection, Arr.Element == Other.Element {
        return Arr(lhs.array + rhs)
    }

    static func + (lhs: Arr<T>, rhs: Arr<T>) -> Arr {
        return Arr(lhs.array + rhs.array)
    }

    static func += <Other>(lhs: inout Arr, rhs: Other) where Other : Sequence, Arr.Element == Other.Element {
        lhs.array += rhs
    }
}

extension Arr: Equatable {
    static func == (lhs: Arr<T>, rhs: Arr<T>) -> Bool {
        return lhs.array == rhs.array
    }
}

extension Arr: CustomStringConvertible {
    var description: String { return "\(array)" }
}

Usage

// init
var array = Arr<Int>()
print(array)
array = Arr(repeating: 0, count: 5)
print(array)
array = Arr([1,2,3,4,5,6,7,8,9])
print(array)

// add
array.append(0)
print(array)
array.append(contentsOf: [5,5,5])
print(array)

// filter
array = array.filter { $0 < 7 }
print(array)

// map
let strings = array.map { "\($0)" }
print(strings)

// insert
array.insert(99, at: 5)
print(array)
array.insert(contentsOf: [2, 2, 2], at: 0)
print(array)

// pop
_ = array.popLast()
print(array)
_ = array.popFirst()
print(array)

// remove
array.removeFirst()
print(array)
array.removeFirst(3)
print(array)
array.remove(at: 2)
print(array)
array.removeLast()
print(array)
array.removeLast(5)
print(array)
array.removeAll { $0%2 == 0 }
print(array)
array = Arr([1,2,3,4,5,6,7,8,9,0])
array.removeSubrange(0...2)
print(array)
array.replaceSubrange(0...2, with: [0,0,0])
print(array)
array.removeAll()
print(array)

array = Arr([1,2,3,4,5,6,7,8,9,0])
print(array)

// subscript
print(array[0])
array[0] = 100
print(array)
print(array[1...4])


// operator functions
array = [1,2,3] + Arr([4,5,6])
print(array)
array = Arr([4,5,6]) + [1,2,3]
print(array)
array = Arr([1,2,3]) + Arr([4,5,6])
print(array)


来源:https://stackoverflow.com/questions/26289413/how-to-subclass-an-array-class-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!