A Swift Tour

本文全面介绍了Swift编程语言的基础知识,包括变量、数据类型、控制流、函数、类与对象等内容,适合初学者快速掌握Swift编程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

About Swift

Swift是一门汲取了CObjective-C的精华,用来开发iOSOS X应用的新的编程语言(由苹果公司于2014年6月7日发布)。Swift摆脱了C语言兼容性的约束,采用安全的编程模式并且添加了现代化的特性,让编程更加容易,灵活和有趣。Swift诞生伊始,在成熟而又深受欢迎的CocoaCocoa Touch框架的支持下,可以重新定位软件开发工作。

Swift是花费了多年打造的编程语言。苹果公司通过改进我们现行的编译器,调试器以及框架底层结构为Swift奠定了基础。我们用ARC(Automatic Reference Counting - 自动引用计数)简化了内存管理。我们的框架栈,是建立在FoundationCocoa这两个框架的坚实基础之上的,并且已经全部使之现代化,标准化。Objective-C它自己已经渐渐完善,支持了blockscollection literals,以及 modules, 使得框架在无破坏的情况下采用现代语言技术。基于这个基础,我们现在能够介绍一门将来用于苹果开发的新的编程语言。

Swift会让Objective-C的开发者感觉很熟悉。它采用了Objective-C参数命名方式的可读性以及动态对象模型。它可以无缝访问现有的Cocoa框架以及与Objective-C混合编程。Swift还介绍了许多新的特性以及结合了语言中面向过程和面向对象的部分

Swift对新的程序员很友好。它兼具编译语言的高性能(Performance)和脚本语言的交互性(Interactive)。它支持的playgrounds, 是一个创新的特性,能够让程序员利用Swift代码在不需要编译和运行app的情况下,马上看到代码所对应的结果。

Swift将现代语言和苹果的工程文化智慧很好的结合起来。编译器在性能方面充分发挥出来,而语言在开发领域充分得到展现,它们之间无须任何妥协。它的设计从"hello world"工程的规模到一个完整的操作系统都得到完整的考虑。所有的一切,让Swift成为所有开发者以及苹果公司未来的福音。

Swift是一种非常优秀的方式去开发iOS以及OS X应用程序,而且在将来继续在新特性和新功能上会更加完善。我们对的Swift未来是十分有信心的,我们已经迫不及待地想看到你用它来开发的产品了。

Hello World

SwiftC语言类似采用一条打印语句来输出“hello world”

println("hello world")

此时此刻,你会想很多问题,main函数在哪?怎么println("hello world")语句后面没有分号?怎么没有程序的返回值?这又是Swift语言的一大特性,程序不需要写任何main函数,执行顺序默认从上到下。每条语句后面也不需要加分号“;”。

变量与常量

C语言中定义常量应该是以const为关键字来定义,而在Swift中我们用的是let关键字。

let myConstant = 10
  • 以上我们就定义了myConstant这个值为10的常量

C语言中定义变量我们没有任何关键字,而Swift中我们采用关键字var来定义

var myVariable = 42
  • 以上我们就定义了myVariable这个值为42的变量

这个时候机智如我的你又有疑问了,常量变量的数据类型去哪了?这又是Swift语言的特性。Swift根据变量(这里所说的变量包括了常量和变量以下如果不作区分都是这个意思)声明时所赋的初始值,自动捕获数据类型(“什么?!自动捕获数据类型,这也太吊炸天了吧!!”)。没错Swift,就是具有这样的功能。随之而来的疑问又是,如果我想只声明变量,不想给它赋值,那它捕捉个鬼啊。的确,如果你在声明变量的时候,如果像这样写let noInitialValue或者var noInitialValue编译器是会报错的。这个时候你要指定它的数据类型了,声明方式如下。

var noInitialValue: Int
noInitailValue = 10
  • 以上声明了一个变量,但是没有赋初始值, 在下一行给它赋值
  • 注意let关键字定义的变量声明的时候绝对不能没有初始值,因为常量在声明之后是不能改变的。但是在类,结构体,枚举类型里面,你可以定义常量属性,然后在它的构造器内进行初始化,不过在其他作用域内不能对它进行更改。

数据类型转换以及字符串(String)插值

变量的数据类型是不能隐式转换的。什么意思呢?在C语言中,浮点型变量是可以直接赋值给整型变量的,只不过会造成精度丢失罢了,并不会报语法错误。而Swift中这样是不允许的,它必须显式的转换。

//隐式转换方式,这样是错误的
var floatValue = 12.5
var intValue: Int
intValue = floatValue
  • 以上是隐式转换方式,这样是错误的
//显式转换方式,这样是正确的
var floatValue = 12.5
var intValue: Int
intValue = Int(floatValue)
  • 以上是显式转换方式,这样是正确的

同样Int型也可以转换成String类型的

//10Apple
let numberOfApples = 10
let fruite = "Apple"
let numberOfFruite = String(numberOfApples) + fruite
  • 以上numberOfFruite的值为“10Apple”

可以转换成字符串类型的数据还有更加快捷的转换方式就是字符串插值在字符串内用一个“\()”的形式,在括号里面加入可以转换成字符串的变量

//10Apple
let numberOfApples = 10
let numberOfOranges = 5
let numberOfFruite = "\(numberOfApples + numberOfOranges)Fruite"
  • 以上numberOfFruite的值为“15Fruite”

数组(Array)和字典(Dictionary)

数字和字典都是用一个方括号的形式定义的“[ ]”。

//数组的定义方式
var​ ​shoppingList​ = [​"catfish"​, ​"water"​, ​"tulips"​, ​"blue paint"​]
​shoppingList​[​1​] = ​"bottle of water"
  • 以上shoppingList的值变为​”catfish”​, ​”bottle of water”​, ​”tulips”​, ​”blue paint”

初始化空数组(有内存地址,但是数组元素为0个)

//指定数据类型的空数组的定义方式let​ ​emptyArray​ = [​String​]()
  • 以上emptyArray的元素个数为0,但是已经确定了数组内的元素必须为String类型”

任意类型的空数组定义方式

//任意数据类型的空数组的定义方式var​ anyType​EmptyArray​ = [​]

//一个确定的数组
let myArray = ["red", "green", "blue"]

//将确定的数组赋值给空数组
anyTypeEmptyArray = myArray

//现在anyTypeEmptyArray[1]的值为"red"
  • 以上anyType​EmptyArray的元素个数为0, 但是不能用anyType​EmptyArray[0] = 1这种方式赋值,只能将已知的数组赋值给这个数组
//字典的定义方式var​ ​occupations​ = [
​    ​"Malcolm"​: ​"Captain"​,
​    ​"Kaylee"​: ​"Mechanic"​,
​]
​occupations​[​"Jayne"​] = ​"Public Relations"
  • 以上occupations的值变为​[“Malcolm”: “Captain” ​, ​”Kaylee”​ : “Mechanic”, ​ “Jayne” : “Public Relations”​]
  • 字典就是以key-value键值对的形式存储的,它的索引方式是通过key来找到对应的value,这里”Malcolm”是key, 这个key所对应的value为”Captain”

初始化空字典(有内存地址,但是字典元素为0个)

//字典的定义方式let​ ​emptyDictionary​ = [String: Float​]()
  • 以上emptyDictionary为空字典,里面没有元素,它的keyString类型,对应的valueFloat类型

任意key类型,value类型的空字典定义方式

//任意key类型,value类型的空字典定义方式var​ anyType​EmptyDictionary = [:​]

// 一个确定的字典类型变量
let myDictionary = ["One": 1, "Two": 2, "Three": 3]

// 将已知字典类型变量myDictionary赋值给anyTypeEmptyDictionary
anyTypeEmptyDictionary = myDictionary

//现在anyTypeEmptyDictionary["One"]对应的值为1
  • 以上anyType​EmptyDictionary 为空字典,里面没有元素,它的key为任意类型,对应的value为任意类型,同样也不能通过anyType​EmptyDictionary["myKey"] = "myValue"的形式赋值,只能将已知字典变量赋值给它

控制流

条件控制流

if-else

if-else条件语句和C语言没什么多大的差别,除了在Swiftif 后面的condition语句不需要添加括号(当然加括号也不会报错),这也是Swift的一大特性,节省了程序员打括号的时间。

let count = 8

if count > 10 {
    println("count is larger than 10")
} else if count > 5 {
    println("count is between 5 and 10")
} else {
    println("count is smaller than 5")
}

//此时控制台打印 "count is between 5 and 10"

iflet 关键字结合使用 if let 可以判断optional类型的可选值是nil还是真的有值,如果有值就将它解包,如果没有值那么不会进入if执行。(关于optional类型,会在后期教程中讲到)

// 定义一个变量为字符串optional类型
var myOptionalString: String? = "Hello"

// if let 可选值绑定,此时myOptionalString 有值"Hello", 则进入if语句
if let str = myOptionalString {
    println(str)
}else{
    println("myOptionalString is nil")
}

//此时控制台打印 "Hello"

// 现在将myOptionalString变为nil相当于C语言的NULL
myOptionalString = nil

// if let 可选值绑定,此时myOptionalString 没有值, 则进入else语句
if let str = myOptionalString {
    println(str)
}else{
    println("myOptionalString is nil")
}

//此时控制台打印 "myOptionalString is nil"
switch-case

关于switch-case控制流语句和C语言以及java语言有比较大的差别。在C语言或者java语言中一般在每个case之后都要加break语句,防止程序一直执行其他对应case之后的所有case。而Swift中则不需要加case语句。在C语言或者java语言中,switch中的default是可加可不加的,而Swift则必须加default语句。

let fruit = "apple"

switch fruit {
case "banana":
    println("The fruit is banana")
case "apple":
    println("The fruit is apple")
case "orange":
    println("The fruit is orange")
default:
    println("I don`t know what the fruit is.")
}

//此时控制台打印 "The fruit is apple"

这个时候或许你又会产生疑问,如果我想让它匹配到case之后继续执行以下语句怎么办?行,满足你的强迫症~Swift可以在每个case中添加fallthrough语句,来满足这个需求。

let whoWantsAnApple = "Bob"

switch whoWantAnApple {
case "Bob":
    println("Bob wants an apple")
    fallthrough
case "Alice":
    println("Alice also wants an apple")
case "Jack":
    println("Jack doesn`t want an apple")
default:
    println("no one wants an apple")
}

//控制台打印
//"Bob wants an apple"
//"Alice also wants an apple"
  • 但是如果case语句里面定义了变量或者常量,就不能用fallthrough

switch-case语句还可以进行区间匹配

let count = 8

switch count {
case 0..<5:
    println("count is between 0 and 5")
case 5..<10:
    println("count is between 5 and 10")
case 10..<15:
    println("count is between 10 and 15")
default:
    println("count is lager than 15")
}

//控制台打印 "count is between 5 and 10"
  • 0..<5表示半开半闭区间 [0,5)

switch-case语句还可以进行条件匹配

let url = "www.apple.com"

switch url {

case let condition where condition.hasSuffix("org"):
    println("it has a suffix 'org'")
case let condition where condition.hasPrefix("www"):
    println("it has a prefix 'www'")
default:
    println("no pattern matches")

}

//控制台打印 "it has a prefix 'www'"

switch 还有许多其他的功能,我在以后的教程中会一一列举。

循环控制流

for

for循环和C++语言以及java中类似,不过在控制变量i初始化声明中,不能用int i声明而得用var i,除此之外Swiftfor循环可以不加括号,但是还是得加分号,另外i++最好改成++i来提高循环体的效率。

let count = 5
for var i = 0; i < count; ++i {
    println("this is count\(count)")
}

//控制台打印
//this is count0
//this is count1
//this is count2
//this is count3
//this is count4
for-in

for-in循环是实际开发中用到最多的循环方式,类似于javafor-each循环,常用来遍历数组和字典

//遍历数组
let animals = ["dog", "panda", "rabbit", "koala"]
let myFavoriteAnimal = "panda"
for animal in animals {
    if animal == myFavoriteAnimal {
        println("\(animal) is my favorite animal")
    }
}

//控制台打印 "panda is my favorite animal"
//遍历字典
let student = ["name": "Jack", "sex": "male", "age":17]

for info in student {
    println("\(info.0) is \(info.1)")
}

//控制台打印
//age is 17
//sex is male
//name is Jack

//也可以这么遍历
let student = ["name": "Jack", "sex": "male", "age":17]

for (key, value) in student {
    println("the key is \(key), and the value is \(value)")
}
//控制台打印
//the key is age, and the value is 17
//the key is sex, and the value is male
//the key is name, and the value is Jack
while

while循环和C语言以及java类似,除了Swiftcondition部分不用加括号

var count = 5
while count > 0 {
    println("Now, count is \(count)")
    count--
}

//控制台打印
//Now, count is 5
//Now, count is 4
//Now, count is 3
//Now, count is 2
//Now, count is 1
do-while

do-while循环也和C语言以及java类似,除了Swift中不用加括号

do {
    println("Now, count is \(count)")
    count--   
} while count > 0

//控制台打印
//Now, count is 5
//Now, count is 4
//Now, count is 3
//Now, count is 2
//Now, count is 1

函数(Function)与闭包(Closures)

函数

函数的声明方式func关键字 + 函数名(函数命名习惯参考Objective-C的函数命名习惯)+ 参数列表(arg0: Type, arg1: Type…) + ‘->’ + 函数返回类型 { 函数体 }

func​ ​greet​(​name​: ​String​, ​day​: ​String​) -> String​ {
​    ​return​ ​"Hello ​\(​name​)​, today is ​\(​day​)​."
​}
let greetStr = ​greet​(​"Bob"​, ​"Tuesday"​)
println(greetStr)

//控制台打印 "Hello Bob, today is Tuesday."
函数返回类型为元组类型
//统计分数的平均值,最小值,最大值
func calculateStatistic(scores: [Int]) -> (average: Float, max: Int, min: Int) {

    var max = scores[0]
    var min = scores[0]
    var sum = 0
    for score in scores {
        max = max < score ? score : max
        min = min > score ? score : min
        sum += score
    }

    let average = Float(sum) / Float(scores.count)

    return (average, max, min)  
}

let scores = [94, 95, 96, 97, 99, 92 ,100]

//result是元组类型,包含了变量average, max, min
let result = calculateStatistic(scores)

println("average = \(result.average), max = \(result.max), min = \(result.min)")

//控制台打印 "average = 96.1429, max = 100, min = 92"

当然,返回类型的元组中,可以省略参数名,只有参数类型

//统计分数的平均值,最小值,最大值, 返回元祖中没有参数名
func calculateStatistic(scores: [Int]) -> (Float, Int, Int) {

    var max = scores[0]
    var min = scores[0]
    var sum = 0
    for score in scores {
        max = max < score ? score : max
        min = min > score ? score : min
        sum += score
    }


    let average = Float(sum) / Float(scores.count)
    return (average, max, min)

}

let scores = [94, 95, 96, 97, 99, 92 ,100]

//result是元祖类型,包含了变量average, max, min的值,但没有变量名
let result = calculateStatistic(scores)

println("average = \(result.0), max = \(result.1), min = \(result.2)")

//控制台打印 "average = 96.1429, max = 100, min = 92"
可变参数列表
func sum(numbers: Int...) -> Int {

    var temp = 0

    for number in numbers {
        temp += number
    }

    return temp
}


let result1 = sum(10, 11, 12, 15)
let result2 = sum(2, 5, 8)

println("result1 = \(result1), result2 = \(result2)")

//控制台输出 "result1 = 48, result2 = 15"
函数嵌套

在Swift中,函数内部还可以定义函数,使用函数,称之为函数嵌套

func​ ​returnFifteen​() -> ​Int​ {
​    ​var​ ​y​ = ​10
​    ​func​ ​add​() {
​        ​y​ += ​5
​    }
​    ​add​()
​    ​return​ ​y
​}
let result = ​returnFifteen​()
println("result is \(result)")

//控制台输出 "result is 15"
函数的返回值是函数

由于是在Swift中函数是first-class类型的,那就意味着函数可以返回一个函数

func getOperationWithOption(option: Character) -> ((Int, Int) -> Int){

    // 加法
    func plus(a: Int, b: Int) -> Int {
        return a + b
    }

    //减法
    func subtract(a: Int, b: Int) -> Int {
        return a - b
    }

    //乘法
    func mutiply(a: Int, b: Int) -> Int {
        return a * b
    }

    //除法
    func divide(a: Int, b: Int) -> Int {
        return a / b
    }


    switch option {
        case "+":
            return plus
        case "-":
            return subtract
        case "×":
            return mutiply
        case "÷":
            return divide
        default:
        return plus
    }
}

let a = 10, b = 2

var operation = getOperationWithOption("+")
let plusResult = operation(a, b)

operation = getOperationWithOption("-")
let subtractResult = operation(a, b)

operation = getOperationWithOption("×")
let mutiplyResult = operation(a, b)

operation = getOperationWithOption("÷")
let divideResult = operation(a, b)

println("plusResult = \(plusResult), subtractResult = \(subtractResult), mutiplyResult = \(mutiplyResult), divideResult = \(divideResult)")

//控制台打印 "plusResult = 12, subtractResult = 8, mutiplyResult = 20, divideResult = 5"
函数的参数是函数
func calculateWithOperation(a: Int, b: Int, operation: (Int, Int) -> Int) -> Int{

    return operation(a, b)
}

// 加法
func plus(a: Int, b: Int) -> Int {
    return a + b
}

//减法
func subtract(a: Int, b: Int) -> Int {
    return a - b
}

//乘法
func mutiply(a: Int, b: Int) -> Int {
    return a * b
}

//除法
func divide(a: Int, b: Int) -> Int {
    return a / b
}


let operations = [plus, subtract, mutiply, divide]

let a = 10, b = 2

for operation in operations {

    let result = calculateWithOperation(a, b, operation)

    println("result = \(result)")
}

//控制台输出 
//result = 12
//result = 8
//result = 20
//result = 5

闭包

函数是闭包的一种特殊形式,闭包相当于”匿名”函数。闭包类似于Objective-C的block,是一个代码块,但是这个代码块并没有名字。

func calculateWithOperation(a: Int, b: Int, operation: (Int, Int) -> Int) -> Int{

    return  operation(a, b)

}

let a = 10, b = 2

////由于是trailing 闭包(即闭包参数为函数参数列表的最后一个)所以闭包可以放到函数最后面用"{ }"来表示

let result = calculateWithOperation(a, b) { (a, b) -> Int in
    a + b
}

println("result is \(result)")

//控制台输出 "result is 12"

闭包格式再简化

func calculateWithOperation(a: Int, b: Int, operation: (Int, Int) -> Int) -> Int{

    return  operation(a, b)

}

let a = 10, b = 2

let result = calculateWithOperation(a, b) { $0 + $1 }

println("result is \(result)")

//控制台输出 "result is 12"
  • 关于函数和闭包的更多内容我会在教程中详细讲的,确实函数和闭包是Swift语法的核心和难点

类与对象

  • 面向对象这部分我会用LOL来举例,如果对LOL不了解的,百度一下或者脑补一下。

类的定义方式

关键字class + 类名 + { 类属性,类方法 }

// 英雄类
class Role {

    // 实例属性:名字
    var name = "DefaultName"

    // 实例属性:角色定位
    var type = "DefaultType"


    // 实例方法: 描述
    func description()-> String {
        return "The role‘s name is \(name), and it is a \(type)."
    }

}
  • func 定义的函数在类里面叫做方法,在类外叫函数

实例化对象

在swift中实例化对象,不需要用new关键字,也不需要像Objective-C语言一样alloc申请内存,init初始化。只需要 类名( ) 就可以了。

// 实例化对象
var role = Role()

// 改变name这个实例属性
role.name = "CustomName"

// 改变type这个实例属性
role.type = "CustomType"

// 调用对象实例的方法
println(role.description())

//控制台打印 "The role's name is CustomName, and it is a CustomType."

构造器

如果你是一个经验丰富的java程序员或者C++程序员就会问,类的构造方法(或者说是构造器)呢?哈哈,你是不是认为我会说Swift没有构造方法?这又是Swift的一大特性?那么对不起,你错了!Swift有构造方法,它的构造方法很奇怪,不是像java那样public Role() { … },也不像C++那样public: Role ( ){ … },它用一个统一的名称叫做init( ) { … }。接下来让我们看看到底是怎么回事吧!

// 拥有构造器的英雄类
class Role {

    // 实例属性:名字
    var name = "DefaultName"

    // 实例属性:角色定位
    var type = "DefaultType"

    // 英雄类的构造器
    init(name : String) {
        self.name = name
    }


    // 实例方法: 描述
    func description()-> String {
        return "The role‘s name is \(name), and it is a \(type)."
    }

}

var role = Role(name: "MyName")

role.type = "MyType"

println(role.description())

//控制台打印 "The role's name is MyName, and it is a MyType."
  • self关键字类似于C++或者java中的this关键字,它用来区分构造器中的参数名和类中 实例属性参数名,self.name 表示该类中定义的var name = “DefaultName”,而name则表示 init(name: String) 中的name。

析构器

Swift和C++一样拥有析构器,析构器主要是用来监测所创建的实例在ARC(自动引用计数)的管理下,对象的内存什么时候被释放,这部分内容我会在后期详细的教程中讲到。

// 拥有析构器的英雄类
class Role {

    // 实例属性:名字
    var name = "DefaultName"

        // 实例属性:角色定位
    var type = "DefaultType"

    //角色类的构造器
    init(name : String) {
        self.name = name
    }


    // 实例方法: 描述
    func description()-> String {
        return "The role‘s name is \(name), and it is a \(type)."
    }


    // 英雄类的析构器
    deinit {

        // 在析构的时候要做些什么
        println("该类被已经析构了")
    }
}

继承

Swift的继承类似于C++, 不同于java那样需要关键字extend。格式如下

class subClass: superClass{

    // TO DO CONFIGURATION

}

属性覆盖和方法覆盖

Swift和大部分面向对象的语言一样,子类继承父类之后,可以覆盖父类的属性和方法,覆盖父类属性,需要在父类构造方法后覆盖。覆盖父类方法,在方法名之前使用关键字override。

// 继承Role类的ADCarry类
class ADCarry: Role {

    //新增加实例属性:射程
    var range: Int

    init(name: String, range: Int){

        //首先初始化子类的属性
        self.range = range

        //其次调用父类的构造方法,初始化name属性
        super.init(name: name)

        //最后修改父类的属性
        self.type = "ADCarry"
    }

    //覆盖父类的方法
    override func description() -> String {
        return super.description() + "Its range is \(range)."
    }
}

实例化子类

let adCarry = ADCarry(name: "Venn", range: 550)

println(adCarry.description())

//控制台打印 "The role's name is Venn, and it is a ADCarry.Its range is 550."

存储属性和计算属性

以上讲到的属性都是类的存储属性。存储属性就是负责存储该类所创建的实例的某些特定的描述。而计算属性是通过getter,setter访问器,通过对象的存储属性的相关运算得到的。如下,在ADCarry这个类添加一个计算属性isLongRange,用来判断这个adc是短手还是长手

class ADCarry: Role {

    //实例属性:射程
    var range: Int

    //根据射程判断,这个adc是长手还是短手
    var isLongRange: Bool {
        get{
            if range > 550 {
                return true
            }else{
                return false
            }
        }

        set{
            if newValue {
                if range <= 550 {
                    println("it is not appropriate to set isLongRange true")
                    self.isLongRange = false
                }
            }else{
                if range > 550 {
                    println("it is not appropriate to set isLongRange false")
                    self.isLongRange = true
                }
            }
        }
    }

    init(name: String, range: Int){

        //首先初始化子类的属性
        self.range = range

        //其次调用父类的构造方法,初始化name属性
        super.init(name: name)

        //最后修改父类的属性
        self.type = "ADCarry"
    }

    //覆盖父类的方法
    override func description() -> String {
        return super.description() + "Its range is \(range)."
    }
}


let adCarry = ADCarry(name: "Venn", range: 550)

println("adCarry`s range is long? \(adCarry.isLongRange)")

adCarry.isLongRange = true


//控制台打印 
"adCarry`s range is long? false"
"it is not appropriate to set isLongRange true"
  • 在上面代码中,在adCarry.isLongRange设置之前,我们并没有指定isLongRange这个属性的true OR false,但是在我们访问的时候,它会自动调用get里面的代码,来计算到底是true还是 false。而当我们要设置isLongRange这个为true的时候,它会调用set里面的代码。你或许会发现set里面有个没有定义的变量叫做newValue。这个变量是Swift“给你的”,当你对计算属性设置新的值后,newValue就存储了这个值。

属性观察者

Swift还给属性添加了属性观察者这个特性,当属性的值将要改变或者改变了的时候会调用观察者内的方法。其中将要改变是用willSet,已经改变是用didSet。下面我们给ADCarry这个类中的range属性添加属性观察者

    //实例属性:射程
    var range: Int {
        willSet{
            println("the range will be setted \(newValue)")
        }
        didSet{
            println("the range has benn setted, and its old value is \(oldValue)")
        }
    }
  • 当我们访问adCarry.range = 500的 时候控制台打印
  • the range will be setted 500
  • the range has benn setted, and its old value is 550

枚举类型

和类的定义方式类似,枚举类型定义方式 关键字enum + 枚举类型名,并且枚举类型同样也可以拥有方法。

enum Rank: Int{
    case Ace = 1

    case Two, ​Three​, ​Four​, ​Five​, ​Six​, ​Seven​, ​Eight​, ​Nine​, ​Ten

    case Jack, ​Queen​, King

    func simpleDescription​() -> String {
        switch self {
        case .Ace:
            return "ace"
        case .Jack:
            return "jack"
        case .​Queen​:
            return "queen"
        case .King:
            return "king"
        default:
            return String(self.rawValue)
        }
    }
}
t ace = Rank.Ace
let aceRowValue = ace.rawValue
println("aceRowValue = \(aceRowValue)")

//控制台输出 "aceRowValue = 1"
  • 注意这里的enum Rank: Int {… }不是指Rank继承Int,而是指Rank的case中的每个值的rowValue是Int类型的

枚举类型的产生可以用init?(rawValue: )的形式

if let convertedRank = Rank(rawValue: 3){
    let threeDescription = convertedRank.simpleDescription()
    println("threeDescription is \(threeDescription)")
}

//控制台输出"threeDescription is 3"

结构体

结构体和类的区别就是类是以引用传递的,结构体是按值传递的。结构体和C语言类似,但也有不同的地方,它也有类的构造器。


struct Role {

    // 属性:名字
    var name = "DefaultName"

    // 属性:角色定位
    var type = "DefaultType"

    //构造器
    init(name : String) {
        self.name = name
    }


    // 结构体方法: 描述
    func description()-> String {
        return "The role‘s name is \(name), and it is a \(type)."
    }

}

let role = Role(name: "strutRole")

// 由于role是常量,而结构体常量,就算它的属性是变量,也不能改变。 role.type = "structType" 是不允许的

println(role.description())

//控制台打印 "The role‘s name is strutRole, and it is a DefaultType."

协议(Protocol)

协议类似java的接口(Interface),在Swift中,也是不允许一个子类继承多个父类的,它用协议的方式来实现类似多重继承的机制。定义方式protocol 协议名 { 属性, 方法 }

protocol RoleAction {

    var attack: Int {get set}

    mutating func modifyAttack()
}

ADCarry这个类继承Role父类,实现RoleAction协议


class ADCarry: Role, RoleAction {

    //新增加实例属性:射程
    var range: Int

    //协议中的attack属性
    var attack = 120

    init(name: String, range: Int){

        //首先初始化子类的属性
        self.range = range


        //其次调用父类的构造方法,初始化name属性
        super.init(name: name)

        //最后修改父类的属性
        self.type = "ADCarry"
    }

    // 实现协议中的方法
    func modifyAttack() {
        attack += 10
    }


    //覆盖父类的方法
    override func description() -> String {
        return super.description() + "Its range is \(range)."
    }
}
  • mutating 关键字结构体中的方法如果要修改结构体内的属性,必须加关键字mutating,然后类中的方法需改类中的属性是不需要加的。由于结构体也可以遵守协议,所以这里的mutating设计是为了让结构体以及类都能遵守这个协议。

扩展(Extension)

扩展,顾名思义,可以让一种数据类型(包括基本数据类型,数组,字典,类,枚举类型,结构体,协议)增加一些属性和方法。对于类来说,有了这样的办法实在太棒了。在java中如果要给某给类加一些属性和方法,是很容易做到的,无论你继承也好,实现结构也好,还是直接修改也好都能实现。如果要让你给Int类型增加一些方法呢?哈哈。不行了吧,下面让Swift带你走进神奇的Extension

extension Int {
    func numberDescription() -> String {
        return "this is a number: \(self)"
    }
}


println(66666.numberDescription())

//控制台输出 "this is a number: 66666"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值