Swift语言 快速基础入门 (2)
本文内容分为两部分,本页是第(2)部分,第一部分请点此浏览:Swift语言 快速基础入门 (1) 对象和类 Objects and Classes类使用class关键字来声明一个类,关键字之后跟着的是类名。类的属性声明和常量以及变量的声明方式完全想通,唯一不同的是他们被声明在类的大括号内。同样的,方法和函数的声明也是如此。
要创建一个类的实例,我们可以在类名后加上括号,比如下面例子中那样。我们可以使用“点语法”(dot syntax)来直接访问实例的属性和方法。
这个版本的 Shape 方法很不靠谱,因为缺少了一个很重要的东西:一个用来设置初始值的方法。我们通常称之为构造函数(constructor、initializer)。在 Swift 中,我们默认通过类中命名为init的方法来作为这个类的构造函数。
1
2
3
4
5
6
7
8
9
10
11
12
|
NamedShape
{
var
numberOfSides
: Int
0
name
: String
init
(
name
: String
{
self
.
name
name
}
{
"A shape with (numberOfSides) sides."
}
注意self是如何被用来区分 name 这个类的属性和 name 这个参数的。第6行中,后面的name 是 init 这个构造函数的参数,而这个参数被传给了 self.name 这个类的属性。
当你创造一个实例的时候,像函数调用参数一样直接给构造器直接传入参数。每一个类的属性都要被赋值,不管是通过直接声明的方式(就像 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
|
class
Square
: NamedShape
{
var
sideLength
: Double
init
(
sideLength
: Double
,
name
: String
)
{
self
sideLength
sideLength
super
name
: name
)
4
}
func
area
->
Double
{
return
sideLength
*
sideLength
}
override
String
{
"A square with sides of length (sideLength)."
}
}
let
test
Square
(
sideLength
:
5.2
name
"my test square"
)
test
)
Getter 和 Setter对于一些简单的属性,可以设置 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
|
class
EquilateralTriangle
: NamedShape
{
sideLength
: Double
0.0
sideLength
: Double
,
{
sideLength
sideLength
super
.
: name
)
3
}
perimeter
{
get
{
3.0
*
sideLength
}
set
{
newValue
/
3.0
}
}
override
{
"An equilateral triagle with sides of length (sideLength)."
}
}
triangle
EquilateralTriangle
(
sideLength
:
3.1
name
"a triangle"
)
triangle
perimeter
perimeter
9.9
sideLength
|
方法 vs 函数
Swift 中,“类中的方法”和一般“函数”有一个重要的区别,那就是参数名。函数的参数名只在函数内部被使用,但是方法的参数名在调用方法时需要写出来。(但是为了对于很多只有一个参数的方法来说简便一点,第一个参数名默认不需要写出)默认地,调用时的参数名与方法内的参数名一样,但是也可以在方法内自定义第二个参数名,具体看下面的例子。
可选值
当使用可选值时,你可以在方法、属性或者子脚本之前加上一个问号?。这样的话,如果问号前的值是 nil,那么问号之后的所有内容都会被忽略,然后整个表达式返回的是 nil。否则,如果问号前的值存在,那么问号后的代码会被运行。这两种情况下,真个表达式的值也都是一个可选值。
枚举和结构 Enumerations and Structures
枚举
使用关键字<span #d333f5;"="" style="box-sizing: border-box; border: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">enum来创建一个枚举。如同类和其他所有被命名的类型一样,枚举可以拥有自己的方法。
在上面的例子中,这个枚举的原始值的类型(raw value type)是整型 Int。所以你只需要设置第一个原始值1,然后剩下的原始值会被自动按照顺序赋值。当然,你也可以使用字符串(String)或者浮点数(Floating-point numbers)作为枚举的原始值。
toRaw和fromRaw函数来实现原始值和枚举值之间的转换。
Rank.fromRaw(1) 就是 Rank.Ace
Rank.Ace.toRaw() 就是 1
枚举的成员值才是重要的,是实际值,并不只是原始值的另一种表示方式。事实上,如果原始值没有什么太大的意义的话我们甚至可以不设置原始值。比如下面的例子就没有设置原始值。
结构体 structure
使用关键字struct来创建一个结构体。 结构体和类有很多相似之处,包括拥有方法和构造函数。他们的一个最最重要的区别是,结构体是传值,被传递的时候永远会被拷贝。但是类被传递是被传递引用。