
(文章出处:http://blog-cn.jiazhewang.com/swift%E8%AF%AD%E8%A8%80-%E5%BF%AB%E9%80%9F%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8-2/)
本文根据《The Swift Programming Language》一书 “A Swift Tour”章节进行了简单地翻译,并加入了一些我个人的实验记录和想法,以求用比较快的速度熟悉 Swift 语言的语法和特性。
本文内容分为两部分,本页是第(2)部分,第一部分请点此浏览:Swift语言 快速基础入门 (1)
对象和类 Objects and Classes 类使用class关键字来声明一个类,关键字之后跟着的是类名。类的属性声明和常量以及变量的声明方式完全想通,唯一不同的是他们被声明在类的大括号内。同样的,方法和函数的声明也是如此。
| 1 2 3 4 5 6 | class Shape { var numberOfSIDes = 0 func simpleDescription ( ) -> String { return "A shape with (numberOfSIDes) sIDes." } } |
要创建一个类的实例,我们可以在类名后加上括号,比如下面例子中那样。我们可以使用“点语法”(dot Syntax)来直接访问实例的属性和方法。
| 1 2 3 | var shape = Shape ( ) shape . numberOfSIDes 7 shapeDescription . simpleDescription ) |
这个版本的 Shape 方法很不靠谱,因为缺少了一个很重要的东西:一个用来设置初始值的方法。我们通常称之为构造函数(constructor、initializer)。在 Swift 中,我们默认通过类中命名为init的方法来作为这个类的构造函数。
1 2 3 4 5 6 7 8 9 10 11 12
当你创造一个实例的时候,像函数调用参数一样直接给构造器直接传入参数。每一个类的属性都要被赋值,不管是通过直接声明的方式(就像 numberOfsIDes)还是通过构造函数(就像name)。
如果你还需要在删除对象之前进行一些清理工作,可以使用命名为deinit的类内方法来创建一个析构函数(deinitializer)。
继承——子类和父类声明子类的方式是在其类名后面写一个冒号,后面跟上父类的名字。由于没有必要继承任何标准的根类,所以我们可以根据实际需要来选择继承或者省略父类。
子类中的方法如果重写了父类的方法,在声明前加关键字overrIDe来标明。如果没有标明的话,会被编译器报错。编译器同样会检测标明了重写但是实际根本没有重写的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20对于一些简单的属性,可以设置 getter 和 setter。比如下面例子中的 perimeter。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
Swift 中,“类中的方法”和一般“函数”有一个重要的区别,那就是参数名。函数的参数名只在函数内部被使用,但是方法的参数名在调用方法时需要写出来。(但是为了对于很多只有一个参数的方法来说简便一点,第一个参数名默认不需要写出)默认地,调用时的参数名与方法内的参数名一样,但是也可以在方法内自定义第二个参数名,具体看下面的例子。
1 2 3 4 5 6 7 8当使用可选值时,你可以在方法、属性或者子脚本之前加上一个问号?。这样的话,如果问号前的值是 nil,那么问号之后的所有内容都会被忽略,然后整个表达式返回的是 nil。否则,如果问号前的值存在,那么问号后的代码会被运行。这两种情况下,真个表达式的值也都是一个可选值。
1 2
使用关键字<span #d333f5;"="" >enum来创建一个枚举。如同类和其他所有被命名的类型一样,枚举可以拥有自己的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22在上面的例子中,这个枚举的原始值的类型(raw value type)是整型 Int。所以你只需要设置第一个原始值1,然后剩下的原始值会被自动按照顺序赋值。当然,你也可以使用字符串(String)或者浮点数(floating-point numbers)作为枚举的原始值。
toRaw和fromraw函数来实现原始值和枚举值之间的转换。
1 2 3
Rank.fromraw(1) 就是 Rank.Ace
Rank.Ace.toRaw() 就是 1
枚举的成员值才是重要的,是实际值,并不只是原始值的另一种表示方式。事实上,如果原始值没有什么太大的意义的话我们甚至可以不设置原始值。比如下面的例子就没有设置原始值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17使用关键字struct来创建一个结构体。 结构体和类有很多相似之处,包括拥有方法和构造函数。他们的一个最最重要的区别是,结构体是传值,被传递的时候永远会被拷贝。但是类被传递是被传递引用。
1 2 3 4 5 6 7 8 9
更具体一点的一些实用性区别是,
类可以被继承而结构体不行;
结构体初始化的时候可以把成员的值直接写在参数中而类不行;
上面的例子中,扑克牌 Card 作为一个包含 Rank 和 Suit 成员的结构体,非常生动。在创建实例的时候,直接使用Card(rank:.ThreesuitSpades)非常清晰。
一个枚举成员的实例可以有对应的实例值(见下面例子中的 ServerResponse.Result(“6:00 am”,“8:09 pm”),时间可以设置成不同,那么就是不同实例值的实例)。相同枚举成员的实例可以有不同的值。当实例被创建的时候,对应的值应该被赋值。
实例值和原始值是不同的:枚举成员的原始值对于所有实例都是相同的,而且原始值是在定义枚举的时候就被定下的。
让我们看一个例子,当要从服务器获取日出和日落的时间的时候,服务器要么返回对应的信息要么返回报错信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14注意 sunrise 和 sunset 时间是怎么作为 switch 中的匹配部分而从 ServerResponse 值中提取出来的。
协议(接口)和扩展 Protocols and Extensions 协议(接口)首先解释一下,苹果从Objective-C 开始,传统意义上的接口,也就是 C#,java,Pascal 等语言中的接口(Interface)就被称为“协议”(protocol)。协议(@protocol)本身不实现任何方法,只声明方法,然后使用此协议的类必须实现协议中的方法。你可以看出,这就是其他语言中“接口”的概念。而 Obj-C 中的“接口”(@interface)只是一个类的声明,声明使用了对应的类。所以我们在学习 Swift 时,看到协议(protocol)的概念,就可以把它当做接口来理解。
protocol来声明一个协议。
1 2 3 4
注意声明结构体的时候用到了mutating这个关键字,它是用来标记一个会修改结构体的方法的。我们知道,结构体不是使用引用传递的,这里和类有些区别。类中不需要使用这个关键字,因为类中所有的方法都是会修改类的。
扩展 extensionextension来为现有的类型增加一些附加功能,比如新方法和计算过的属性。你可以使用扩展来给任意在别处声明的类型添加一致性的协议,或者甚至直接添加到从外部库或者框架中导入的类型。
1 2 3 4 5 6 7 8 9
上面这个拓展直接拓展了整型Int,给所有整型数据增加了一些方法和属性。
protocolValue a protocolValue simpleDescription // protocolValue.anotherProperty// Uncomment to see the error我们可以直接使用协议名(比如例子中的 ExampleProtocol)来作为一种类型。它表示了所有应用了这个协议的类型的集合。比如例子中的 ExampleProtocol 就表示了 SimpleClass 类和 SimpleStructure 结构体的集合的类型。这个类型拥有所有协议规定的属性和方法,但是不具有每个类型自身衍生的属性和方法,比如 SimpleClass 中,有协议没有规定的额外属性 anotherProperty。这个属性 ExampleProtocol 类型的实例就没有,不能访问。即使 protocolValue 在运行时的类型是 SimpleClass,编译器也会把它当做 ExampleProtocol 类型。所以不可以调用类在协议以外声明的属性或者方法了。
泛型 Generics在尖括号<>里写一个名字来创建一个泛型函数或者是类型。通过泛型我们可以创建不需要规定应用类型的对象。
1 2 3 4 5 6 7 8
在类型名后使用关键字where来指定一个需求列表:比如,要求此类型应用一个协议,要求两个类型相同,或者要求一个继承特定的父类。
| 1 2 3 4 5 6 7 8 9 10 11 | func anyCommonElements < U where T : Sequence U GeneratorType Element : Equatable Element == U Element > @H_965_419@lhs : T rhs : U Bool { for lhsItem in lhs { @H_965_419@rhsItem rhs { if lhsItem rhsItem { true } } } false } anyCommonElements [ 1 3 ] 比如上面的例子中声明了一个泛型函数,需要使用两个参数,分别是泛型 T 和泛型 U。并对它们分别做出了限定。 简单一点的话,也可以直接省略 where 关键字,只在冒号后面写上协议名或者类名来限定此类型应用该协议和次类型继承该父类。比如<T:Equatable>等价于<Twhere> 。总结 以上是内存溢出为你收集整理的Swift语言 快速基础入门 (2)全部内容,希望文章能够帮你解决Swift语言 快速基础入门 (2)所遇到的程序开发问题。 如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。 欢迎分享,转载请注明来源:内存溢出 赞
(0) 打赏
微信扫一扫
支付宝扫一扫
swift2.0 UIColor Use RGB 上一篇
2022-05-27 在Swift中,使用SDWebImage做缓存后获取缩略图的大小。
下一篇2022-05-27 |
微信扫一扫
支付宝扫一扫
评论列表(0条)