味道

作者: newbaner | 来源:发表于2016-08-12 17:36 被阅读34次

    想念你的笑
    想念你的外套
    想念你白色袜子
    和身上的味道
    我想念你的吻
    和手指淡淡烟草味道
    记忆中曾被爱的味道
    ----For Swift

    2ca603ec-0911-43b3-837f-becd2671a58e.png

    咳咳```一不小心唱起来了,味道。
    说点实在的,Swift的味道还真是不得不让人迷醉。
    三周之前,我不认识你,你不属于我;三周之后,我依然不认识你,你也不属于我。唯有的,只有我记住了你的一些味道:袜子味儿、辣椒味儿、火药味儿、无重复的味儿……当然,更多的,是清香味儿,来的轻盈,散的清凉。


    容器

    “Swift provides three primary collection types, known as arrays, sets, and dictionaries, for storing collections of values”

    Swift 用来存储数据的三种类型:数组、集合、容器

    - 数组

    数组有三种最重要的运算:过滤、映射、缩减

    let array = [2,24,56,96,68,88,44,37,1]
    //1.过滤
    let newarray = array.filter { $0 % 2 == 0}
    print(newarray)//过滤奇数  [2, 24, 56, 96, 68, 88, 44]
    
    //2.映射
    let newArray2 = array.map { $0*$0}//每个对应平方
    print(newArray2)//[4, 576, 3136, 9216, 4624, 7744, 1936, 1369, 1]
    
    //3.缩减
    let reduce1=array.reduce(0, combine: +)
    print(reduce1)//416
    
    
    

    - 集合

    以hash code/哈希码/散列码 来存储数据,使用时很快就能找到其中某个数据的位置和值,型如:var a:Set<Int> = [1,1,5,4,2]
    对集合的操作:
    1.增删

    a.insert(100)     //添加元素
    a.remove(1)     //   删除元素
    print(a)          //  [5, 100, 2, 4]
    

    2.交并差子

    var b:Set<Int> = [1,2,33,7]
    print(a.intersect(b))//交集    [2]
    print(a.union(b))    //并集    [2, 4, 5, 100, 7, 1, 33]
    print(a.subtract(b))  //差集  [5, 100, 4]
    var c:Set<Int>  =  [5,100]
    print(c.isSubsetOf(a))//判断子集(Bool)  true
    
    

    - 字典

    字典的每个元素都是由两个方面组成,冒号前是键,冒号后是值
    通过键获取对应的值(可空类型,因为给的键有可能没有对应的值)
    如:

    var dict :[String:String] = ["abacus":"算盘","abnomal":"异常","hello":"你好","good":"好"]
    print(dict["hello"]!)  //你好
    print(dict["sss"])   //nil
    

    遍历字典

    for value in dict.values{
        print(value)
    }
    
    for key in dict.keys{
        print(key)
    }
    for (key,value) in dict{
        
        print("\(key)-->\(value)")
    }
    /*结果:
    abnomal
    shit
    hello
    good
    abnomal-->异常
    shit-->🐶💩
    hello-->你好
    good-->好
    */
    

    枚举

    两种相反的事物,我们义无反顾的选择Bool类型,那么超过两种但却又相互对立的事物,怎么描述呢?那么枚举就是必不可少的了。利用自定义的枚举类型,可以在项目中任意调用其中一种事件,比如,扑克有四种花色,利用枚举,就可以便捷的定义区分花色了

    花色枚举
    - Spade: ♠️
    - Heart: ♥️
    - Club: ♣️
    - Diamond: ♦️

    enum Suite:String{
        case Spade = "♠️",Heart = "♥️",Club = "♣️",Diamond = "♦️"
    }
    
    ……
    ……
    
    let suites = [Suite.Spade, .Heart,.Club,.Diamond]
    
    

    函数

    swift中,函数也是一种类型,这也意味着函数可以作为常量或者变量的类型。
    同理,函数可以作为另一个函数的参数或者返回值.

    - 尾随闭包

    闭包:就是Java和C#中的 lambda函数(lambda表达式)、JS中的匿名函数,C中的B look起相同作用的,他存在的意义是,实现代码的解耦合
    毕竟,写代码的终极目的,高类聚,低耦合
    闭包的形式为:

      { (parameters) -> return type in
        statements
      } 
    

    这里的return可以省略。如果函数的最后一个参数是闭包,可以写成尾随闭包的形式,也就是将闭包放到函数参数的圆括号外面写一对花括号中;如果函数后面有尾随闭包且函数的圆括号里没有参数,那么圆括号可以省。

    尾随闭包
    如果函数的最后一个参数是闭包。可以将该参数放到函数的花括号内,省略圆括号()

    reversed = names.sort { $0 > $1 }
    

    数组names降序排列。
    $0表示第一个参数
    $1表示第二个参数

    - 递归调用

    递归,指的就是一个函数直接或间接调用自身的方法,其条件为:
    1.递归公式
    2.收敛条件
    简单举个例子,用递归方法可以算1-100的求和:

    func sss(n:Int)->Int{
        if n==1{
            return 1
        }
        return n + sss(n-1)
    }
    

    这里的sss函数,两个分支,一个是当n!=1的时候,再次调用自身,就是计算100的函数要调用99的函数,99的函数需要调用98的函数……直到调用到1,直接返回1,即可求出结果。这里,递归公式就是函数的return n + sss(n-1),递归条件是,当n==1的时候,停止递归,返回 给上一次的递归结果1.
    经典应用:汉诺伊塔

    func hanluoita(n:Int,_ a:String,_ b:String,_ c:String)
    {
        if n>0{
            hanluoita(n-1, a, c, b)
            print("\(a)--->\(b)")
            hanluoita(n-1, c, b, a) 
        } 
    }
    hanluoita(5, "A", "B", "C")
    

    物以类聚,人以群分。故名思义,类,就是具有相同的属性的一个概括。
    定义一个类主要有四个步骤:
    发现类

    • 在对问题的描述中找名词和动词
    • 名词会成为类或者类中的属性 动词会成为类中的方法

    定义类

    • 定义类可以创建新的类型,类名每个首字母大写;
    • 数据抽象--找到和学生相关的属性(找名词)
    • 初始化方法\构造方法--创建对象要使用的方法--constructor
    • 行为抽象--找到和学生相关的方法(找动词)
      变量定义在类里,叫属性;函数写在类里面,叫方法

    创建对象

    • 调用初始化方法

    给对象发消息

    • 通过给对象发消息来解决问题

    面向对象

    面向对象七原则:(为了实现高类聚、低耦合)
    • 单一职责原则(SRP)
      每个类应该专注于做一件事情哦

    • **开闭原则(OCP) **
      面向扩展开放,面向修改关闭

    • 依赖倒转原则(面向抽象编程, DIP)
      实现尽量依赖抽象,不依赖具体实现

      爱人, 待周爱人而后为爱人
      《墨子·取周》

    • **里氏替换原则(LSP) **
      能用父类型的地方就一定可以使用子类型.超类存在的地方,子类是可以替换的

      白马, 马也, 乘白马, 乘马也
      黑马, 马也, 乘黑马, 乘马也
      娣, 美人也, 爱娣非爱美人也
      盗, 人也, 恶盗非恶人也
      《墨子·小取》

    • ** 接口隔离原则(ISP)**
      应当为客户端提供尽可能小的单独接口,而不是提供大的总的接口

    • 合成聚合复用原则(CARP)
      尽可能使用合成/聚合达到复用,尽量少用继承。原则:一个类中有另一个类的对象

    • 迪米特法则(LoD)
      一个软件实体应当尽可能少的与其他实体发生相互作用

    继承

    继承: 从已有的类创建新类的过程
    提供继承信息的称为父类(超类/基类);得到继承信息的称为子类(派生类/衍生类)
    通常子类除了得到父类的继承信息还会增加一些自己特有的东西
    所以子类的能力一定比父类更强大.
    继承的意义在于子类可以复用父类的代码并且增强系统现有的功能.

    继承特点:
    • 可以将子类型的对象赋值给父类型的变量(因为子类跟父类之间是IS-A关系)
    • 如果要将父类型的变量转换成子类型需要用as运算符进行类型转换
    • 如果能够确认父类型的变量中就是某种子类型的对象可以用as!进行转换
    • 如果不确定父类型的变量中是哪种子类型可以用as?尝试转换
    • 定义方法参数类型的时候尽可能使用父类型(抽象类型).因为如果用父类型的参数调用方法时可以传入任意子类型对象

    多态

    同样的对象类型接收相同的消息(调用相同的方法),但是做了不同的事情 这就是多态(polymorphism)
    实现多态的关键步骤:

    1. 方法重写 override (子类在继承父类的过程中对父类已有的方法进行重写, 而且不同的子类给出各自不同的实现版本)
      父类有的方法子类可以重新实现 这个过程叫方法重写,需要在方法前添加override关键字.重写有时也被称为置换/覆盖/覆写
    2. 对象造型(将子类对象当成父类型来使用)

    可以通过if+as?将父类型安全的转换成子类型然后再调用子类特有方法

    一些技能GET ✔️

    • 便利构造器
      我们可以在一个类中定义多个初始化方法
      便利初始化方法 / 便利构造器:
      调用了其他的初始化方法的初始化方法
     convenience init() {
            self.init(x: 0, y: 0)
        }
        convenience init(point: (Double, Double)) {
            self.init(x: point.0, y: point.1)
        }
        ```
      **指派初始化方法 / 指派构造器**:
        被其他初始化方法调用的初始化方法
    

    init(x: Double, y: Double) {
    self.x = x
    self.y = y
    }

    
       -  **计算属性**
    在定义类的属性的时候,有两种方式:
    存储属性:负责存储变量的值
    计算属性:负责将存储数据进行计算返回新的值,有get和set方法
    如果不允许修改的变量,就没有set方法,通过私有的方法保护原来的值。
    

    //存储属性
    private var _name: String
    private var _hp: Int
    private var _mp: Int

    //计算属性
    var isAlive: Bool {
    get { return _hp > 0 }
    }
    var name: String {
    get { return _name }
    }
    var hp: Int {
    get { return _hp }
    set { _hp = newValue > 0 ? newValue : 0 }
    }
    var mp: Int {
    get { return _mp }
    }

    
       - ** 扩展 **
    如果在某个特定的应用场景中发现现有的类缺失了某项功能
    那么可以通过扩展(extension)的方式现场添加这项功能
    

    extension Point {
    var cgPoint: CGPoint {
    get { return CGPointMake(CGFloat(x), CGFloat(y)) }
    }
    }

    比如我在画布画贝塞尔曲线的时候,需要把点的坐标转换为CGFloat,就可以现场添加一个函数实现功能。
    
       -  **运算符重载**
                 当我们自己定义的函数也需要进行计算的时候,我们又想直接利用系统的运算符号,那么就可以对系统的符号函数进行运输符重载(+、-、*、/、%、><……都是系统制定的一个函数)
    

    //对小于符号进行重载
    func <(one: Student, two: Student) -> Bool {
    return one.name < two.name
    }

    重载后,可以直接调用<符号进行运算:
    
    

    let stuArray = [
    Student(name: "Wang Dachui", age: 24),
    Student(name: "Lee Xiaolong", age: 49),
    Student(name: "Zhang Nima", age: 18),
    Student(name: "Guo Jing", age: 26)
    ]
    // let newArray = stuArray.sort { $0.age > $1.age }
    let newArray = stuArray.sort(<)
    for stu in newArray {
    print("(stu.name): (stu.age)")
    }

    输出以名字的首字母升序排列:
    Guo Jin*: 26
    Lee Xiaolon*: 49
    Wang Dachu*: 24
    Zhang Nim*: 18
    
    * * *
    环境果然促人成长,不知几个月后,是怎样的五味杂陈……
    ###嘿,s  w  i  f  t  e  r
    
    ![20160310231228_UduMR.jpeg](https://img.haomeiwen.com/i2670532/265efea2086917a7.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    相关文章

      网友评论

          本文标题:味道

          本文链接:https://www.haomeiwen.com/subject/falesttx.html