Swift getter 和 setter 具有不同签名的下标

Swift subscript with different signature for the getter and setter

是否可以在 Swift 中包含一个 subscript,它对 gettersetter 具有不同的签名?

例如,我希望 getter 到 return 一个 Set<Int> 并且 setter 需要一个 Int(而不是 Set<Int>).

此代码无法编译,但它可以让您了解我正在尝试做什么:

struct Foo{

    subscript(index: Int)->String{
        get{
            return "bar" // returns a String
        }
        set(newValue: String?){ // takes a String? instead of a String
            print(newValue)
        }
    }
}

我该怎么做?

这非常丑陋,我强烈建议您不要这样做,但从技术上讲这是可能的:

struct Foo {

    subscript(concreteValueFor index: Int) -> String {
        return "Get concrete \(index)"
    }

    subscript(optionalValueFor index: Int) -> String? {
        get { return nil }
        set { print("Set optional \(index)") }
    }

}

var foo = Foo()

foo[concreteValueFor: 1]            // Returns "Get concrete 1"
foo[optionalValueFor: 2] = ""       // Prints "Set optional 2"

前段时间我做了一个多图:

public struct Multimap<Key: Hashable, Value: Hashable>: CollectionType {

    public typealias _Element = Set<Value>
    public typealias Element = (Key, _Element)
    public typealias Index = DictionaryIndex<Key, _Element>
    public typealias Generator = DictionaryGenerator<Key, _Element>

    private typealias Storage = [Key: _Element]

    private var storage = Storage()

    public var startIndex: Index { return storage.startIndex }
    public var endIndex: Index { return storage.endIndex }

    public subscript(position: Index) -> _Element { return storage[position].1 }
    public subscript(position: Index) -> Element { return storage[position] }

    subscript(key: Key) -> Set<Value> {
        get { return storage[key] ?? Set<Value>() }
        set { storage[key] = newValue.isEmpty ? nil : newValue }
    }

    public func generate() -> Generator { return storage.generate() }

}

用法:

var foo = Multimap<Int, String>()

foo[0]                      // Returns an emtpy Set<String>
foo[0].insert("Ook")        // Inserts a value at index 0
foo[0].insert("Eek")
foo[0]                      // Now this returns a set { "Ook", "Eek" }
foo[1].insert("Banana")
foo[1].insert("Book")
foo[0].unionInPlace(foo[1])
foo[0]                      // Returns a set { "Banana", "Ook", "Eek", "Book" }