zoukankan      html  css  js  c++  java
  • Swift编程语言中如何实现自定义类型的for-in循环(基于Swift 2.2)

    我们在Swift编程语言中常常会用到for-in循环(在编程语言术语中又被称为for-each)。此外,从Swift 2.2版本起,for循环将只支持for-in形式,而不支持for i = 0; i < n; i+=1 { }这种形式了,若要使用这种形式的话,只得用while或repeat-while来代替,或想办法转为for-in。

    在Swift中,标准库已经定义了许多类型可直接支持for-in循环形式,比如Range、Array、Set、Dictionary等等。那么我们是否能自己定义一个类或结构体来支持for-in这种迭代形式呢?当然可以!我们要实现这个目标需要分两步走。

    第一步,我们要使用for-in循环的类或结构体需要实现SequenceType这个协议。SequenceType包含了许多容器相关的接口方法,但如果我们只需要简单实现for-in循环的话,那么只需要实现其 public func generate() -> Self.Generator 接口方法即可。这里的Self只能用在protocol的定义内,相当于self,但是这里又不能用self,因为self是对对象的引用,协议不是一个对象,所以Swift编程语言中引入了Self(注意S是大写的)表示引用本协议内定义的类型。generate方法用于生成所需迭代的每个元素的列表。此外,Generator的本体是GeneratorType,它也是一个protocol,表示所需迭代的每个元素对象,所以我们要做第二步。

    第二步,实现GeneratorType协议。这个协议比较简单,就一个 public mutating func next() -> Self.Element 接口方法。这里的Element可用来指定每个元素的类型。

    下面我们就看一下一个实例代码:

    //
    //  ViewController.swift
    //  SwiftTest
    //
    //  Created by Zenny Chen on 16/4/1.
    //  Copyright © 2016年 GreenGames Studio. All rights reserved.
    //
    
    import Cocoa
    
    class MyIterContainer<T> : SequenceType {
        
        // 容器本身包含一个数组对象mElemArray
        private var mElemArray: [T]?
        
        init() {
            mElemArray = [T]()
        }
        
        init(elems: [T]) {
            mElemArray = elems;
        }
        
        func generate() -> MyIterGenerator<T> {
            
            // 这里返回一个GeneratorType对象
            return MyIterGenerator(elems: mElemArray!)
        }
    }
    
    class MyIterGenerator<T> : GeneratorType {
        
        private var mCurrentIndex: Int = 0
        private var mElemArray: [T]?
        
        init(elems: [T]) {
            
            mElemArray = elems
        }
        
        func next() -> T? {
            
            guard let list = mElemArray else { return  nil }
            
            if mCurrentIndex < list.count {
                
                let element = list[mCurrentIndex]
                mCurrentIndex += 1
                return element
                
            }
            else {
                return nil
            }
        }
    }
    
    class ViewController: NSViewController {
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            // Do any additional setup after loading the view.
            
            let container = MyIterContainer(elems: [1, 2, 3, 4])
            
            var sum = 0
            for i in container {
                sum += i
            }
            print("sum = (sum)")
            
            sum = 0
            
            // 上述的for-in迭代就相当于以下代码:
            let generator = container.generate()
            var elem: Int? = nil
            
            repeat {
                elem = generator.next()
                if let value = elem {
                    sum += value
                }
            }
            while elem != nil
            
            print("second sum = (sum)")
        }
        
        override var representedObject: AnyObject? {
            didSet {
                // Update the view, if already loaded.
            }
        }
    }
    

    上述示例代码先定义了一个容器类MyIterContainer<T>,然后定义了与之相关的生成器类MyIterGenerator<T>,这里用了泛型,可使得后面的实现更为灵活。然后在viewDidLoad方法中描述了for-in的使用方法,并且在最后描述了其内部实现机制。

  • 相关阅读:
    remove white space from read
    optimize the access speed of django website
    dowload image from requests
    run jupyter from command
    crawl wechat page
    python version 2.7 required which was not found in the registry windows 7
    health
    alternate rows shading using conditional formatting
    word
    【JAVA基础】static 关键字
  • 原文地址:https://www.cnblogs.com/zenny-chen/p/5352514.html
Copyright © 2011-2022 走看看