Как подкласс класса массива в Swift?

Я новичок в Swift. У меня есть базовый класс:

class foo{}

Я хочу реализовать класс коллекции foo:

class foos: Array<foo>{}

Но компилятор жалуется:

наследование из не-протокола, неклассового типа "Массив"

Я пробовал другой синтаксис (например, [foo] и NSMutableArray<foo>), но ни один из них не прошел проверку компилятора.

Это должно быть просто, но я весь день искал в googled и не мог понять. Кто-нибудь знает, если это возможно, и если это так, правильный синтаксис?

Ответ 1

Тип Swift Array - это структура, а в Swift базовые классы должны быть действительными классами (т.е. class Foo), а не структурами.

Таким образом, вы не можете делать то, что вы пытаетесь сделать через наследование от Array, к сожалению. Тем не менее, вы можете хранить массив как поле внутри вашего класса и пересылать ему методы, возможно, используя любые протоколы, которые вы хотите поддерживать, и так далее.

Ответ 2

В Swift массив представляет собой структуру, а не класс. Чтобы иметь класс, являющийся подклассом массива, вам нужно будет использовать NSArray, его сопоставление Objective-C.

Например,

class Foo: NSArray{}

Ответ 3

В Swift 2.x вы можете использовать расширение протокола.

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 {}
Расширения протокола

предоставляют "точки вставки" для расширения классов, которые не являются классами, классами, которыми вы не являетесь, и т.д.

Ответ 4

подробности

  • Xcode 10.1 (10B61)
  • Swift 4.2

идея

Вы можете создать собственный массив, используя протокол RangeReplaceableCollection.

Образец

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)" }
}

использование

// 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)