swift2.docx

上传人:b****8 文档编号:27665815 上传时间:2023-07-03 格式:DOCX 页数:22 大小:24.04KB
下载 相关 举报
swift2.docx_第1页
第1页 / 共22页
swift2.docx_第2页
第2页 / 共22页
swift2.docx_第3页
第3页 / 共22页
swift2.docx_第4页
第4页 / 共22页
swift2.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

swift2.docx

《swift2.docx》由会员分享,可在线阅读,更多相关《swift2.docx(22页珍藏版)》请在冰豆网上搜索。

swift2.docx

swift2

在if语句中,条件必须是一个布尔表达式——这意味着像ifscore{...}这样的代码将报错,而不会隐形地与0做对比。

你可以一起使用if和let来处理值缺失的情况。

这些值可由可选值来代表。

一个可选的值是一个具体的值或者是nil以表示值缺失。

在类型后面加一个问号来标记这个变量的值是可选的。

varoptionalString:

String?

="Hello"

print(optionalString==nil)

varoptionalName:

String?

="JohnAppleseed"

vargreeting="Hello!

"

ifletname=optionalName{

greeting="Hello,\(name)"

}

如果变量的可选值是nil,条件会判断为false,大括号中的代码会被跳过。

如果不是nil,会将值赋给let后面的常量,这样代码块中就可以使用这个值了。

另一种处理可选值的方法是通过使用?

?

操作符来提供一个默认值。

如果可选值缺失的话,可以使用默认值来代替。

letnickName:

String?

=nil

letfullName:

String="JohnAppleseed"

letinformalGreeting="Hi\(nickName?

?

fullName)"

TheSwiftProgrammingLanguage中文版

时间简史

本页内容包括:

简单值(SimpleValues)

控制流(ControlFlow)

函数和闭包(FunctionsandClosures)

对象和类(ObjectsandClasses)

枚举和结构体(EnumerationsandStructures)

协议和扩展(ProtocolsandExtensions)

泛型(Generics)

通常来说,编程语言教程中的第一个程序应该在屏幕上打印“Hello,world”。

在Swift中,可以用一行代码实现:

print("Hello,world!

")

如果你写过C或者Objective-C代码,那你应该很熟悉这种形式——在Swift中,这行代码就是一个完整的程序。

你不需要为了输入输出或者字符串处理导入一个单独的库。

全局作用域中的代码会被自动当做程序的入口点,所以你也不需要main()函数。

你同样不需要在每个语句结尾写上分号。

这个教程会通过一系列编程例子来让你对Swift有初步了解,如果你有什么不理解的地方也不用担心——任何本章介绍的内容都会在后面的章节中详细讲解。

注意:

为了获得最好的体验,在Xcode当中使用代码预览功能。

代码预览功能可以让你编辑代码并实时看到运行结果。

下载Playground

简单值

使用let来声明常量,使用var来声明变量。

一个常量的值,在编译的时候,并不需要有明确的值,但是你只能为它赋值一次。

也就是说你可以用常量来表示这样一个值:

你只需要决定一次,但是需要使用很多次。

varmyVariable=42

myVariable=50

letmyConstant=42

常量或者变量的类型必须和你赋给它们的值一样。

然而,你不用明确地声明类型,声明的同时赋值的话,编译器会自动推断类型。

在上面的例子中,编译器推断出myVariable是一个整数(integer)因为它的初始值是整数。

如果初始值没有提供足够的信息(或者没有初始值),那你需要在变量后面声明类型,用冒号分割。

letimplicitInteger=70

letimplicitDouble=70.0

letexplicitDouble:

Double=70

练习:

创建一个常量,显式指定类型为Float并指定初始值为4。

值永远不会被隐式转换为其他类型。

如果你需要把一个值转换成其他类型,请显式转换。

letlabel="Thewidthis"

letwidth=94

letwidthLabel=label+String(width)

练习:

删除最后一行中的String,错误提示是什么?

有一种更简单的把值转换成字符串的方法:

把值写到括号中,并且在括号之前写一个反斜杠。

例如:

letapples=3

letoranges=5

letappleSummary="Ihave\(apples)apples."

letfruitSummary="Ihave\(apples+oranges)piecesoffruit."

练习:

使用\()来把一个浮点计算转换成字符串,并加上某人的名字,和他打个招呼。

使用方括号[]来创建数组和字典,并使用下标或者键(key)来访问元素。

最后一个元素后面允许有个逗号。

varshoppingList=["catfish","water","tulips","bluepaint"]

shoppingList[1]="bottleofwater"

varoccupations=[

"Malcolm":

"Captain",

"Kaylee":

"Mechanic",

]

occupations["Jayne"]="PublicRelations"

要创建一个空数组或者字典,使用初始化语法。

letemptyArray=[String]()

letemptyDictionary=[String:

Float]()

如果类型信息可以被推断出来,你可以用[]和[:

]来创建空数组和空字典——就像你声明变量或者给函数传参数的时候一样。

shoppingList=[]

occupations=[:

]

控制流

使用if和switch来进行条件操作,使用for-in、for、while和repeat-while来进行循环。

包裹条件和循环变量括号可以省略,但是语句体的大括号是必须的。

letindividualScores=[75,43,103,87,12]

varteamScore=0

forscoreinindividualScores{

ifscore>50{

teamScore+=3

}else{

teamScore+=1

}

}

print(teamScore)

在if语句中,条件必须是一个布尔表达式——这意味着像ifscore{...}这样的代码将报错,而不会隐形地与0做对比。

你可以一起使用if和let来处理值缺失的情况。

这些值可由可选值来代表。

一个可选的值是一个具体的值或者是nil以表示值缺失。

在类型后面加一个问号来标记这个变量的值是可选的。

varoptionalString:

String?

="Hello"

print(optionalString==nil)

varoptionalName:

String?

="JohnAppleseed"

vargreeting="Hello!

"

ifletname=optionalName{

greeting="Hello,\(name)"

}

练习:

把optionalName改成nil,greeting会是什么?

添加一个else语句,当optionalName是nil时给greeting赋一个不同的值。

如果变量的可选值是nil,条件会判断为false,大括号中的代码会被跳过。

如果不是nil,会将值赋给let后面的常量,这样代码块中就可以使用这个值了。

另一种处理可选值的方法是通过使用?

?

操作符来提供一个默认值。

如果可选值缺失的话,可以使用默认值来代替。

letnickName:

String?

=nil

letfullName:

String="JohnAppleseed"

letinformalGreeting="Hi\(nickName?

?

fullName)"

switch支持任意类型的数据以及各种比较操作——不仅仅是整数以及测试相等。

letvegetable="redpepper"

switchvegetable{

case"celery":

print("Addsomeraisinsandmakeantsonalog.")

case"cucumber","watercress":

print("Thatwouldmakeagoodteasandwich.")

caseletxwherex.hasSuffix("pepper"):

print("Isitaspicy\(x)?

")

default:

print("Everythingtastesgoodinsoup.")

}

练习:

删除default语句,看看会有什么错误?

注意let在上述例子的等式中是如何使用的,它将匹配等式的值赋给常量x。

运行switch中匹配到的子句之后,程序会退出switch语句,并不会继续向下运行,所以不需要在每个子句结尾写break。

你可以使用for-in来遍历字典,需要两个变量来表示每个键值对。

字典是一个无序的集合,所以他们的键和值以任意顺序迭代结束。

letinterestingNumbers=[

"Prime":

[2,3,5,7,11,13],

"Fibonacci":

[1,1,2,3,5,8],

"Square":

[1,4,9,16,25],

]

varlargest=0

for(kind,numbers)ininterestingNumbers{

fornumberinnumbers{

ifnumber>largest{

largest=number

}

}

}

print(largest)

练习:

添加另一个变量来记录现在和之前最大数字的类型。

使用while来重复运行一段代码直到不满足条件。

循环条件也可以在结尾,保证能至少循环一次。

varn=2

whilen<100{

n=n*2

}

print(n)

varm=2

repeat{

m=m*2

}whilem<100

print(m)

你可以在循环中使用..<来表示范围,也可以使用传统的写法,两者是等价的:

varfirstForLoop=0

foriin0..<4{

firstForLoop+=i

}

print(firstForLoop)

varsecondForLoop=0

forvari=0;i<4;++i{

secondForLoop+=i

}

print(secondForLoop)

使用..<创建的范围不包含上界,如果想包含的话需要使用...。

 

函数和闭包

使用func来声明一个函数,使用名字和参数来调用函数。

使用->来指定函数返回值的类型。

funcgreet(name:

String,day:

String)->String{

return"Hello\(name),todayis\(day)."

}

greet("Bob",day:

"Tuesday")

练习:

删除day参数,添加一个参数来表示今天吃了什么午饭。

使用元组来让一个函数返回多个值。

该元组的元素可以用名称或数字来表示。

funccalculateStatistics(scores:

[Int])->(min:

Int,max:

Int,sum:

Int){

varmin=scores[0]

varmax=scores[0]

varsum=0

forscoreinscores{

ifscore>max{

max=score

}elseifscore

min=score

}

sum+=score

}

return(min,max,sum)

}

letstatistics=calculateStatistics([5,3,100,3,9])

print(statistics.sum)

print(statistics.2)

函数可以带有可变个数的参数,这些参数在函数内表现为数组的形式:

funcsumOf(numbers:

Int...)->Int{

varsum=0

fornumberinnumbers{

sum+=number

}

returnsum

}

sumOf()

sumOf(42,597,12)

练习:

写一个计算参数平均值的函数。

函数可以嵌套。

被嵌套的函数可以访问外侧函数的变量,你可以使用嵌套函数来重构一个太长或者太复杂的函数。

funcreturnFifteen()->Int{

vary=10

funcadd(){

y+=5

}

add()

returny

}

returnFifteen()

函数是第一等类型,这意味着函数可以作为另一个函数的返回值。

funcmakeIncrementer()->(Int->Int){

funcaddOne(number:

Int)->Int{

return1+number

}

returnaddOne

}

varincrement=makeIncrementer()

increment(7)

函数也可以当做参数传入另一个函数。

funchasAnyMatches(list:

[Int],condition:

Int->Bool)->Bool{

foriteminlist{

ifcondition(item){

returntrue

}

}

returnfalse

}

funclessThanTen(number:

Int)->Bool{

returnnumber<10

}

varnumbers=[20,19,7,12]

hasAnyMatches(numbers,condition:

lessThanTen)

函数实际上是一种特殊的闭包:

它是一段能之后被调取的代码。

闭包中的代码能访问闭包所建作用域中能得到的变量和函数,即使闭包是在一个不同的作用域被执行的-你已经在嵌套函数例子中所看到。

你可以使用{}来创建一个匿名闭包。

使用in将参数和返回值类型声明与闭包函数体进行分离。

numbers.map({

(number:

Int)->Intin

letresult=3*number

returnresult

})

练习:

重写闭包,对所有奇数返回0。

有很多种创建更简洁的闭包的方法。

如果一个闭包的类型已知,比如作为一个回调函数,你可以忽略参数的类型和返回值。

单个语句闭包会把它语句的值当做结果返回。

letmappedNumbers=numbers.map({numberin3*number})

print(mappedNumbers)

你可以通过参数位置而不是参数名字来引用参数——这个方法在非常短的闭包中非常有用。

当一个闭包作为最后一个参数传给一个函数的时候,它可以直接跟在括号后面。

当一个闭包是传给函数的唯一参数,你可以完全忽略括号。

letsortedNumbers=numbers.sort{$0>$1}

print(sortedNumbers)

对象和类

使用class和类名来创建一个类。

类中属性的声明和常量、变量声明一样,唯一的区别就是它们的上下文是类。

同样,方法和函数声明也一样。

classShape{

varnumberOfSides=0

funcsimpleDescription()->String{

return"Ashapewith\(numberOfSides)sides."

}

}

练习:

使用let添加一个常量属性,再添加一个接收一个参数的方法。

要创建一个类的实例,在类名后面加上括号。

使用点语法来访问实例的属性和方法。

varshape=Shape()

shape.numberOfSides=7

varshapeDescription=shape.simpleDescription()

这个版本的Shape类缺少了一些重要的东西:

一个构造函数来初始化类实例。

使用init来创建一个构造器。

classNamedShape{

varnumberOfSides:

Int=0

varname:

String

init(name:

String){

self.name=name

}

funcsimpleDescription()->String{

return"Ashapewith\(numberOfSides)sides."

}

}

注意self被用来区别实例变量。

当你创建实例的时候,像传入函数参数一样给类传入构造器的参数。

每个属性都需要赋值——无论是通过声明(就像numberOfSides)还是通过构造器(就像name)。

如果你需要在删除对象之前进行一些清理工作,使用deinit创建一个析构函数。

子类的定义方法是在它们的类名后面加上父类的名字,用冒号分割。

创建类的时候并不需要一个标准的根类,所以你可以忽略父类。

子类如果要重写父类的方法的话,需要用override标记——如果没有添加override就重写父类方法的话编译器会报错。

编译器同样会检测override标记的方法是否确实在父类中。

classSquare:

NamedShape{

varsideLength:

Double

init(sideLength:

Double,name:

String){

self.sideLength=sideLength

super.init(name:

name)

numberOfSides=4

}

funcarea()->Double{

returnsideLength*sideLength

}

overridefuncsimpleDescription()->String{

return"Asquarewithsidesoflength\(sideLength)."

}

}

lettest=Square(sideLength:

5.2,name:

"mytestsquare")

test.area()

test.simpleDescription()

练习:

创建NamedShape的另一个子类Circle,构造器接收两个参数,一个是半径一个是名称,在子类Circle中实现area()和simpleDescription()方法。

除了储存简单的属性之外,属性可以有getter和setter。

classEquilateralTriangle:

NamedShape{

varsideLength:

Double=0.0

init(sideLength:

Double,name:

String){

self.sideLength=sideLength

super.init(name:

name)

numberOfSides=3

}

varperimeter:

Double{

get{

return3.0*sideLength

}

set{

sideLength=newValue/3.0

}

}

overridefuncsimpleDescription()->String{

return"Anequilateraltriaglewithsidesoflength\(sideLength)."

}

}

vartriangle=EquilateralTriangle(sideLength:

3.1,name:

"atriangle")

print(triangle.perimeter)

triangle.perimeter=9.9

print(triangle.sideLength)

在perimeter的setter中,新值的名字是newValue。

你可以在set之后显式的设置一个名字。

注意EquilateralTriangle类的构造器执行了三步:

设置子类声明的属性值

调用父类的构造器

改变父类定义的属性值。

其他的工作比如调用方法、getters和setters也可以在这个阶段完成。

如果你不需要计算属性,但是仍然需要在设置一个新值之前或者之后运行代码,使用willSet和didSet。

比如,下面的类确保三角形的边长总是和正方形的边长相同。

classTriangleAndSquare{

vartriangle:

EquilateralTriangle{

willSet{

square.sideLength=newValue.sideLength

}

}

varsquare:

Square{

willSet{

triangle.sideLength=newValue.sideLength

}

}

init(size:

Double,name:

String){

square=Square(sideLength:

size,name:

name)

triangle=EquilateralTriangle(sideLength:

size,name:

name)

}

}

vartriangleAndSquare=TriangleAndSquare(size:

10,name:

"anothertestshape")

print(triangleAndSquare.square.sideLength)

print(triangleAndSquare.triangle.sideLength)

triangleAndSquare.square=Square(sideLength:

50,name:

"largersquare")

print(triangleAndSquare.triangle.sideLength)

处理变量的可选值时,你可以在操作(比如方法、属性和子脚本)之前加?

如果?

之前的值是nil,?

后面的东西都会被忽略,并且整个表达式返回nil。

否则,?

之后的东西都会被运行。

在这两种情况下,整个表达式的值也是一个可选值。

letoptionalSquare:

Square?

=Squar

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 笔试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1