免费开源的iOS开发学习平台

Swift:10 类和结构体

类和结构体是Swfit语言的核心内容之一。在Swfit中类和结构体有很多相同的特性,比如都有属性、方法、下标、构造器、扩展和协议等特性,同时,类又有结构体所不具有的特性:继承、类型转换、析构和引用计数等。跟Objective-C相比,Swift中的类没有.h头文件。

类和结构体基本用法

类和结构体的定义语法相似。通过关键词class来引入一个类,通过struct关键词来引入一个结构体。他们的定义都在一对花括号中:

struct point{
    var x:Int = 0
    var y:Int = 0
}
class map {
    //可选类型的属性
    var name:String?
    var po = point()
}

使用类或者结构体名后面加上括号"()",就可以调用它们的构造函数来对类或结构体进行实例化。可以通过在实例后面加上点”.“语法来访问类和结构体的属性。所有结构体都有一个自动生成的成员构造器( memberwise initializer),可以用来初始化新的结构体实例的成员属性。新的实例的初始值可以通过名字传递给成员构造器。

struct point{
    var x:Int = 0
    var y:Int = 0
}
class map {
    //可选类型的属性
    var name:String?
    var po = point()
}
//成员构造器
var p1 = point(x:10,y:20)
var m1 = map()

m1.name = "地图1"
m1.po = p1

print("\(m1.name!)中的po的坐标点是(\(m1.po.x),\(m1.po.y))")
//打印结果:地图1中的po的坐标点是(10,20)

结构体和枚举是值类型

Swift中所有的基础类型,比如整数、浮点数、布尔值、字符串、数组和字典的类型都是值类型,所有的结构体和枚举也都是值类型,也就是说在代码中传递的时候,结构体和枚举实例以及他们的值类型的属性都会被复制。

enum color{
    case R,G,B,A
}
struct point{
    var x:Int = 0
    var y:Int = 0
}

var c1 = color.R
var c2 = c1

c2 = .G

if c1 == color.R {
    print("枚举是值传递")
}

var p1 = point(x:10,y:10)
var p2 = p1
p2.y = 20

print("p1的坐标是(\(p1.x),\(p1.y))")
print("p2的坐标是(\(p2.x),\(p2.y))")

代码运行结果如下图。

类是引用类型

跟Objective-C中的类一样,Swift中的类是引用类型。比较两个引用类型是否相等的运算符是恒等(===)和(!==)不恒等。

class map {
    //可选类型的属性
    var name:String?
}

var m1 = map()

m1.name = "地图1"

var m2 = m1

m2.name = "地图2"

if m1 === m2 {
    print("m1恒等于m2")
}
print("m1.name = \(m1.name!),m2.name=\(m2.name!)")

//打印结果:m1恒等于m2
//        m1.name = 地图2,m2.name=地图2

如何选择类和结构体

一般地,在满足如下的一个或几个条件的情况下使用结构体:

  • 封装一些相关的简单的数据值
  • 有必要通过副本而非引用来赋值或者传递
  • 所有属性本身是值类型,也是用来复制而非引用
  • 不需要从已有类型集成属性或者行为

除以上几种情况外,基本上都选择类来构建数据类型。

集合类型的赋值和拷贝行为

Swift中,Array和Dictionary类型是按照结构体实现的。也就是说当把数组和字典以及其他的结构体赋值给常量或者变量以及传递给函数或者方法时会发生值拷贝的行为。
和Foundation中的NSArray以及NSDictionary不一样(他们是类实现),NSArray和NSDictionary实例始终是按照引用赋值和传递的,而不是拷贝。

示例代码

https://github.com/99ios/23.11