【问题标题】:Swift operator `subscript` []Swift 运算符`下标` []
【发布时间】:2015-11-04 04:08:32
【问题描述】:

我是Swift 的初学者,对操作员一无所知。

我有以下课程

class Container {
   var list: [Any] = [];
}

我想实现运算符subscript [] 以便访问来自list 的数据。

我需要这样的东西:

var data: Container = Container()
var value = data[5]
// also    
data[5] = 5

我也希望能够写出这样的东西:

data[1][2]

是否有可能考虑到 Container 中的元素 1array

感谢您的帮助。

【问题讨论】:

    标签: swift operator-overloading subscript-operator


    【解决方案1】:
    class Container
    {
        var list: [AnyObject] = ["hello" , "world"];
        subscript ( i : Int) -> AnyObject{
            get{
                return list[i]
            }
            set{
                list[i] = newValue
            }
        }
    }
    
    var c : Container = Container()
    println(c[1])
    
    c[1] = "lol"
    
    println(c[1])
    

    有关运营商的更多信息:http://nshipster.com/swift-operators/

    【讨论】:

      【解决方案2】:

      这里好像有两个问题。

      1。如何在我自己的自定义类上启用subscripting

      要在您的类Container 上启用subscripting,您需要像这样实现subscript 计算属性。

      class Container {
          private var list : [Any] = [] // I made this private
      
          subscript(index:Int) -> Any {
              get {
                  return list[index]
              }
              set(newElm) {
                  list.insert(newElm, atIndex: index)
              }
          }
      }
      

      现在你可以这样使用它了。

      var container = Container()
      container[0] = "Star Trek"
      container[1] = "Star Trek TNG"
      container[2] = "Star Trek DS9"
      container[3] = "Star Trek VOY"
      
      container[1] // "Star Trek TNG"
      

      2。我可以访问Container 的一个元素,它支持像data[1][2] 这样的下标写作吗?

      如果我们不使用您的示例,则您不能。因为data[1] 返回Any 类型的东西。而且你不能下标Any

      但如果你添加一个演员,它就成为可能

      var container = Container()
      container[0] = ["Enterprise", "Defiant", "Voyager"]
      (container[0] as! [String])[2] // > "Voyager"
      

      【讨论】:

        【解决方案3】:

        听起来您正在寻找下标。您可以为自己的类型制作下标,如下例所示:

        class Container {
            var list = [["Hello", "World"], ["Foo", "Bar"]]
        
            subscript(index: Int) -> [String] {
                get {
                    return list[index]
                }
                set {
                    list.insert(newValue, atIndex: index)
                }
            }
        }
        

        上面的例子只适用于双重[ ],因为我知道我们将返回一个Array。这里Array 包含字符串作为示例,但您当然可以换成自己的类型

        var container = Container()
        
        container[0][0] = "Stack"
        container[0][1] = "Overflow"
        
        print(container[0][0]) // "Stack"
        print(container[1][1]) // "Bar"
        

        【讨论】:

          【解决方案4】:

          一种解决方法是利用subscript 中的多个参数

          所以你可以说data[1, 2],而不是data[1][2]。这在某些情况下会很方便

          struct Container {
            subscript(a: Int, b: Int) -> String {
              print(a)
              print(b)
              return "possible"
            }
          }
          
          let data = Container()
          data[1, 2]
          

          【讨论】:

            【解决方案5】:

            Swift 5.2:在 UserDefaults 值中下标 - 有用的管理器

            具有泛型类型的静态函数

            class Defaults {
            
               static subscript<T>(key: DefaultsKey) -> T? {
                  get {
                    return UserDefaults.standard.value(forKey: key.rawValue) as? T
                  }
                  set {
                    UserDefaults.standard.set(newValue, forKey: key.rawValue)
                  }
                }
            }
            
            enum DefaultsKey: String {
                case firstKey = "JSGHDjasgchvsas"
            }
            

            节省价值

            Defaults[.firstKey] = 34
            

            获得价值

            let value: Int = Defaults[.firstKey]
            

            编码愉快!

            【讨论】:

              【解决方案6】:
              class Container {
                  private var list = [Any]()
                  subscript(_ index: Int) -> Int? {
                     get {
                          guard index < list.count else { return nil }
                          return list[index]
                    }
                     set(newValue){
                        guard let unwrappedElement = newValue else { return }
                        list.insert(unwrappedElement, at: index)
                     }
                  }
              }
              

              这里我们使用可选类型的下标来处理超出范围的索引。

              【讨论】:

              • 我知道这是一篇旧帖子(也是巧妙的解决方案),但从技术上讲,这不应该导致崩溃吗?返回 nil 可能会产生无法预料的后果,并且也不符合下标的工作方式。至少它应该引发越界异常或什么?
              • 你引用了“但这在技术上不应该导致崩溃吗?”签名```下标(_索引:Int)-> Int?```说,它会保证返回值,返回值可以是期望的请求访问或在不存在的情况下为零
              • 在你的代码中处理崩溃肯定是你想要的。
              猜你喜欢
              • 1970-01-01
              • 2014-04-19
              • 1970-01-01
              • 1970-01-01
              • 2013-12-08
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多