Swift(2)

可选类型(?)

隐式解析可选类型(!)

结构体

协议

扩展

闭包

demo截图.png
import Foundation

//MARK:--------------------Swift中的"?"和"!"--------------------
/*
  1. 在swift中可选类型(optionals),用"?"表示,用于处理值缺失的情况,表示"这儿有一个值,且它等于x"或者表示"这儿没有值"
  2. 可选类型是一个包含两种情况的枚举值,None和Some,用来表示可能有值或可能没有值
     2.1. nil就是Optional.None,当声明一个可选变量或者可选属性的时候,没有提供初始值,它的值默认为nil
     2.2. 非nil就是Optional.Some
  3. 任何类型都可以明确地声明为可选类型,当声明一个可选类型时,要确保用括号给"?"操作符一个合适的范围。例如:声明可选整数数组,应该写成"(Int[])?",如果写成"Int[]?",就会报错
*/

// 定义一个可选类型:以下两种声明方式是相等的
var Optional_1 : Int?// 在数据类型和"?"之间没有空格
var Optional_2 : Optional<Int>
var intNumber : Int? = 100
// 打印出来以后是一个Optional类型的值
print(intNumber)
// 如果要取到100,必须对可选类型强制解析
print(intNumber!)

// 4. "!":用来强制解析,如果可选类型实例包含一个值,可以用"!"来访问这个值
// 注意:可选类型分为有值和没值,如果可选类型的变量没值时对其强制解包,程序就会崩溃,如下面的程序:
/*
var Number : Int?
print(Number!)
*/

/*
   5. 自动解析(隐式解析)
     5.1 可以在声明可选变量时,使用"!"来替换"?",这样可选变量在使用时就不需要再加一个"!"来取值了,它会自动解析
     5.2 隐式解析可选类型,和可选类型一样,都是有值和没有值(nil)两种结果
     5.3 区别是赋值时,隐式解析可选类型不需要再强制解析
     5.4 注意:隐式解析可选类型的变量没有值时,程序一样会崩溃
*/
var IntNumberOne : Int! = 10
print(IntNumberOne)

/*
   6. 可选绑定
      6.1 可选绑定:用来判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者临时变量
      6.2 可选绑定可以用在if和while语句中来对可选类型的值进行判断,并把它赋给一个常量或者变量
      6.3 如果不确定可选类型是否有值,用可选绑定,不需要对可选类型强制解析
*/
var intNumberTwo:Int?
if var intNumberThree = intNumberTwo
{
    print("可选类型有值 = ", intNumberThree)
}
else
{
    print("可选类型无值")
}
//MARK:----------------------Swift中的结构体---------------------
/*
 1. 与C和OC不同的是:
    1.1 结构体不需要包含实现文件和接口文件
    1.2 结构体允许我们创建一个单一文件,且系统会自动生成该结构体用于面向其他代码的外部接口
 2. 结构体总是通过被复制的方式在代码中传递,因此,原本结构体的值是不可修改的
 3. 结构体的应用
    3.1 在代码中,可以使用结构体定义自定义数据类型
    3.2 按照通用的准则,当符合一条或者多条以下条件时,请考虑构建结构体
        3.2.1 结构体的主要目的是用来封装少量相关简单数据
        3.2.2 有理由预计一个结构体实例在赋值或者传递时,封装的数据将会被拷贝而不是引用
        3.2.3 任何结构体中存储的值类型属性,也将会被拷贝,而不是被引用
        3.2.4 结构体不需要去继承另一个已存在类型的属性或者行为
 4. 例如:
    4.1 几何形状的大小,封装一个width属性和height属性,两者均为double类型
    4.2 一定范围的路径,封装一个start属性和length属性,两者均为    Int类型
    4.3 三维坐标系内的一点,x,y,z属性,三者均为double类型
*/
// 格式:struct + 结构体名字 + {结构体实现}

struct Frame
{
    // 存储属性 就是类或结构体里定义的变量(或常量)
    var x : Float
    var y : Float
    var width : Float
    var height : Float
    
    // 计算属性 除存储属性外,类、结构体和枚举可以定义计算属性.计算属性不直接存储值,而是提供一个getter和一个可选的setter,来间接获取和设置其他属性或变量的值
    // get方法 :在属性类型后面添加{},使用get关键字声明和实现get方法
    // set方法 :同上
    // set方法不可以单独出现,必须搭配着get方法才可以出现,但是get方法可以单独出现
    var centerX : Float {
        get{
            return x + width / 2
        }
    }
    var centerY : Float {
        get{
            return y + height / 2
        }
    }
    // 结构体属性  只能通过结构体去调用
    static var myStruct = "我是一个结构体属性"
    // 结构体中可以声明和实现成员方法即函数
    func sayHI()
    {
        print("你好,我是一个方法")
    }
    // 结构体的类方法:方法前用static修饰,只能由结构体调用
    static func sayHello()
    {
        print("hello")
        // 结构体类方法中只能调用结构体属性
        print(self.myStruct)
    }
    // 结构体自带有初始化方法,但是也可以重写
    init(x newX : Float, y newY : Float, width newWidth : Float, height newHeight : Float)
    {
        x = newX
        y = newY
        width = newWidth
        height = newHeight
    }
}
// 调用结构体属性(因为是结构体属性,所以只能由结构体调用,不能由对象调用)
print(Frame.myStruct)
// 调用结构体的类方法
Frame.sayHello()

// 结构体有自带的构造体方法和初始化方法
// 以下这两种创建对象的方式没区别
var frame : Frame = Frame(x: 10, y: 10, width: 100, height: 100)
var frame1 : Frame = Frame.init(x: 10, y: 10, width: 100, height: 100)
print(frame.centerX)
// 调用Frame结构体的成员方法
frame1.sayHI()

//MARK:-----------------------Swift中的类-----------------------
// 类是人们构建代码所用的一种通用且灵活的构造体。我们可以使用与结构体完全相同的语法规则来为类定义属性(常量、变量)和添加方法
/*
 1. swift中,类和结构体有很多共同点
    1.1 定义属性,用于存储值
    1.2 定义方法,用于提供功能
    1.3 定义构造器,用于提供初始化值
    1.4 遵循协议,用来对某个类提供标准功能
    1.5 通过扩展,用来增加默认实现的功能
 2. 与结构体相比,又有其他附加功能
    2.1 继承,允许一类继承另一个类的特征
    2.2 类型转换允许在运行时检查和解释一个类实例的类型
    2.3 引用计数:允许对一个类多次引用
*/
// 值类型:该类型的每个实例持有数据的副本,并且该副本对于每个实例来说是独一无二的一份,比如结构体(struct)、枚举(enum)、元组(tuple)都是值类型
/*
值类型的使用场景:
    当使用"=="运算符比较数据的时候
    想单独复制一份实例数据的时候
    在多线程环境下操作数据的时候
*/
/*
// 创建一个StructObject结构体变量
struct StructObject
{
    var data : Int = -1
}
var a = StructObject()
// b是a的拷贝
var b = a
// 更改a的数据,b的不受影响
a.data = 42
print("\(a.data), \(b.data)")
*/

// 引用类型:该类型的实例共享数据唯一的一份副本(在native层面说的话,就是该类型的每个实例都指向内存中的同一个地址),比如类(class)就是引用类型

/*
// 创建一个ClassObject类
class ClassObject
{
    var data : Int = -1
}
var a = ClassObject()
// 将a变量的值赋值给b,其实是一个引用的过程
var b = a
// a的数据改变了,但是b也发生了改变
a.data = 42
print("\(a.data), \(b.data)")
*/

/*
使用值类型的情形:
   使用 == 运算符比较实例数据的时候
   单独复制一份实例数据的时候
   在多线程环境下操作数据的时候
使用引用类型(比如class)的情形:
   使用 == 运算符判断两个对象是否引用同一个对象实例的时候
   当上下文需要创建一个共享的、可变的对象时
*/

// 类的定义格式:class + 类名 + {类的实现}
class Person
{
    // 当给一个类写属性的时候,这个属性如果没有初值那就需要是可选类型
    // 存储属性
    var name : String?
    var gender : String?
    var age : Int?
    
    // 计算属性
    var width : Float {
        get{
            return 100
        }
        set{
            // set方法中的newValue表示新的值
            self.width = newValue
        }
    }
    // 此处static修饰的是类属性
    static var hooby : String? = "大播"
    // 此处static修饰的是类方法,这时类方法可以调用static修饰的类属性
    static func sayMy()
    {
        print(hooby!)
    }
    // 没用static修饰的类方法不能调用static修饰的属性
    func sayHI()
    {
        print("你好啊\(self.width)")
        name = "污唐"
    }
    // 声明类方法时,static和class都可以修饰类方法,区别在于class修饰的类方法可以被子类重写。class修饰的类方法可以调用static修饰的属性,但是class自己不能修饰属性
    class func saySaWaDiKa()
    {
        print(hooby!)
    }
    // 类的构造方法  系统没有自带,需要自己写了才能调用
    init(name newName : String, gender newGender : String, age newAge : Int)
    {
        name = newName
        gender = newGender
        age = newAge
    }
}
// 创建实例对象的两种方式(这两种方式没区别):
var person : Person = Person.init(name: "王梁", gender: "女", age: 8)
var person1 : Person = Person(name: "鸭王", gender: "女", age: 3)
// 调用实例对象的属性
print(person.age!)
// 实例person1调用实例方法sayHI()
person1.sayHI()
// 类Person调用static修饰的类方法sayMy()
Person.sayMy()
// 类Person调用class修饰的类方法saySaWaDiKa()
Person.saySaWaDiKa()

class student : Person
{
    var number : NSString?
    
    // 重写父类的方法 :需要添加override修饰
    override func sayHI()
    {
        print("重写方法")
    }
    // 重写父类的init构造方法
     override init(name newName : String, gender newGender : String, age newAge : Int)
    {
        super.init(name: newName, gender: newGender, age: newAge)
        name = newName
        gender = newGender
        age = newAge
    }
    // 在重新创建一个init方法的时候 还是需要super.init
    init(number newNumber : NSString)
    {
        super.init(name: "张三", gender: "男", age: 1)
        number = newNumber
    }
}
var stu1 : student = student.init(name: "小明", gender: "男", age: 9)
stu1 = student.init(number: "007")
print(stu1.name!,stu1.number!)
stu1.sayHI()

//MARK:----------------------Swift中的协议-----------------------
/*
  协议定义了一个蓝图,规定了用来实现某一特定工作或者功能所必需的方法和属性
  类、结构体或枚举类型都可以遵循协议,并提供具体实现来完成协议定义的方法和功能
  任意能够满足协议要求的类型被称为遵循(conform)这个协议
*/

// 声明协议
// protocol声明的协议,表示Swift的协议,所有的方法都必须实现
protocol myDelegate
{
    // 协议方法
    func test()
    // 使用mutating修饰的函数,可以在结构体里面修改结构体的属性
    // 在协议里面使用mutating修饰的函数,在遵守协议的时候,类里面不能使用mutating修饰。但是在结构体里面,如果要修改属性的话必须用mutating修饰方法
    mutating func change()
}
// @objc修饰的协议表示这个协议是OC的协议,可以声明可选实现的函数,在函数名前面用optional修饰,这个函数就是可选实现的了
@objc protocol newDelegate
{
    optional func newTest()
    func newChange()
}

class Teacher : Person, myDelegate, newDelegate {
    // 必须实现的方法
    func test()
    {
        name = "111"
        print("aaa")
    }
    // 必须实现的方法
    @objc func newChange()
    {
        
    }
    // 必须实现的方法
    // 协议里面使用mutating修饰的函数,在类里面就是一个普通的函数
    func change()
    {
        name = "100"
    }
    // 可选实现的方法
    @objc func newTest()
    {
        
    }
}
let teacher :Teacher = Teacher(name: "a", gender: "b", age: 111)
teacher.test()

// @objc修饰的协议 结构体不能遵循
struct myStruct : myDelegate
{
    var name : String
    // 一般不能直接修改结构体里面的属性
    func test()
    {
        
    }
    // mutating修饰的方法里可以修改结构体的属性
    mutating func change()
    {
        name = "111"
    }
}

//MARK:----------------------Swift中的扩展-----------------------
// extension + 类名(结构体名字) 可以对一个类或结构体扩展方法
// extension不能扩展属性
// extension也可以给类或结构体扩展协议方法 这个在开发的时候最有用

extension Person : myDelegate // 给Person类扩展协议
{
    // 实现协议里的方法
    func test()
    {
        
    }
    // 实现协议里的方法
    func change()
    {
        
    }
    // 给Person类扩展方法
    func eat()
    {
        
    }
}
extension Frame : myDelegate // 给Frame结构体扩展协议
{
    // 实现协议里的方法
    func test()
    {
        
    }
    // 实现协议里的方法
    func change()
    {
        
    }
    // 给Frame结构体扩展新的方法
    func play()
    {
        
    }
}

//MARK:----------------------Swift中的闭包-----------------------
/*
   * 闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift中的闭包与C和Objective-C中的代码块(block)以及其他一些编程语言中的匿名函数比较相似。
   * 闭包可以捕获和存储其所在上下文中任意常量和变量的引用。这就是所谓的闭合并包裹着这些常量和变量,俗称闭包。Swift会为您管理在捕获过程中涉及到的所有内存操作。
   * 语法格式:
     {
        (参数) -> 返回值类型 in
        执行语句
     }
   * 注意:闭包的函数体部分由关键字in引入。该关键字表示闭包的参数和返回值类型定义已经完成,闭包函数即将开始。
*/

// 使用闭包求两个Int型数的最大值
// 声明一个闭包
var maxValue : ((Int, Int) -> Int)

// 实现闭包的第一种方式
maxValue = {
    (a : Int, b : Int) -> Int in
    return a > b ? a :b
}
/*
   其中:
   * maxValue的类型是(Int, Int) -> Int
   * maxValue的值就是一个闭包:
      {
         (a : Int, b : Int) -> Int in
         return a > b ? a :b
      }
*/
// 第二种方式实现闭包 省略参数类型和返回值
maxValue = {
    a, b in
    return a > b ? a : b
}
// 第三种方式实现闭包 省略参数类型,省略返回值,省略return关键字
maxValue = {
    a, b in
    a > b ? a : b
}
// 第四种方式 都省略了 使用$表示取第几个参数
maxValue = {
    $0 > $1 ? $0 : $1
}
// 第五种 苹果推荐的格式
maxValue = {
    (a, b) -> Int in
    return a > b ? a : b
}
print(maxValue(3,5))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,873评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,483评论 1 306
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,525评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,595评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,018评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,958评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,118评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,873评论 0 208
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,643评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,813评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,293评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,615评论 3 262
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,306评论 3 242
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,170评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,968评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,107评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,894评论 2 278

推荐阅读更多精彩内容