结构体的介绍
- 结构体是由一系列具有相同类型或者不同类型的数据结构构成的数据集合
- 结构体是一种数据结构
- 结构体是数值类型,在方法中传递时是值传递
- 结构体的特点
- 定义属性存储值
- 定义方法用于提供功能
- 定义构造器便于生成初始值
- 定义下标操作使得可以通过下标语法来访问实例所包含的值
- 通过扩展以增加默认实现的功能
结构的定义
- 用struct 来结构体,并在一对大括号中定 义它们的具体内容
struct 结构体名称 {
//在这里定义结构体,可以是属性,方法等
}
//定义一个结构体
struct Point {
//实例属性
var X:Double = 0.0;
var Y:Double = 0.0;
//实力方法
func distance(num1:Double,num2:Double) -> Double {
return num1*num2;
}
//类型方法
static func test() {
print("测试")
}
}
//类型方法 static func 相当于 OC中的类方法 直接访问 Point.test()
//实力方法 func
let juli = Point.init(X: 2.5, Y: 2.6);
print(juli.distance(num1: juli.X, num2: juli.Y));
//注意:无论是 枚举 还是 结构体 都可以写方法
}
结构体的应用
struct Point {
var X:Double
var Y:Double
}
//2点的距离
func distance (p1:Point,p2:Point) ->Double {
return sqrt(pow(p1.X - p2.X, 2) + pow(p1.Y - p2.Y, 2));
}
let p1 = Point.init(X: 4, Y: 5);
let p2 = Point.init(X: 0, Y: 0);
let result = distance(p1: p1, p2: p2);
print(result);
//结果:6.40312423743285
结构体的 构造函数
- 所有结构体都有一个自动生成的成员逐一构造器,用于初始化新结构体实例中成员的属性。新实例中各个属性的初始值可以通过属性的名称传递到成员逐一构造器之中
struct Point {
//声明2个属性
var X:Double
var Y:Double
}
//逐一构造器
let p1 = Point.init(x: 10, y: 20);
- 自定义构造函数 (相当于OC 中的init方法 重写)
- 自定义构造函数不加func
- 在构造函数内部,必须保证所有的非可选属性都必须有值
- 我们在自定义构造函数时,系统定义的就没有了
truct Point {
var X:Double
var Y:Double
var Z:Double
//构造函数 类似OC中的初始化
//不加 func
//在构造函数内部,必须保证,所有的非可选属性,必须有值
//如果我们现在自己定义的构造函数,那么系统自动生成的逐一构造函数器,就没有了
//自定义构造函数
init(x:Double,y:Double) {
self.X = x;
self.Y = y;
Z = 0;
}
//重写系统 逐一构造函数器
init(x:Double,y:Double,z:Double) {
self.init(x: x, y: y);
self.Z = z;
}
}
let p1 = Point.init(x: 10, y: 20);
print(p1)
//打印结果: Point(X: 10.0, Y: 20.0, Z: 0.0)
let p2 = Point.init(x: 20, y: 30, z: 40);
//打印结果:40.0 20.0 30.0
定义其他函数(类型函数和实例函数)
- 创建实例方法
- 默认情况下:在函数里面,是无法修改实例属性的
- 除非:使用关键字 mutating 进行修饰,让self可以改变才可以
truct Point {
var X:Double
var Y:Double
var Z:Double
//构造函数 类似OC中的初始化
init(x:Double,y:Double) {
self.X = x;
self.Y = y;
self.Z = 0;
}
init(x:Double,y:Double,z:Double) {
self.init(x: x, y: y);
self.Z = z;
}
//创建实例方法
//默认情况下:在函数里面,是无法修改实例属性的
// 除非:使用关键字 mutating 进行修饰,让self可以改变才可以
mutating func moveX(disX:Double) {
return self.X += disX;
}
}
var p1 = Point.init(x: 10, y: 20);
p1.moveX(disX: 60);
struct Point {
var X:Double
var Y:Double
var Z:Double
//构造函数 类似OC中的初始化
init(x:Double,y:Double) {
self.X = x;
self.Y = y;
self.Z = 0;
}
init(x:Double,y:Double,z:Double) {
self.init(x: x, y: y);
self.Z = z;
}
//类型方法
static func SeeX(pointX:Double) {
print(pointX);
}
}
//调用
Point.SeeX(pointX: 10);
机构体是值类型
- 值类型被赋予给一个变量、常量或者被传递给一个函数的时候,其值会被拷贝
- 注意:所有的基本类型:整数(Integer)、浮 点数(floating-point)、布尔值(Boolean)、字符串(string)、数组(array)和字典(dictionary),都是 值类型,并且在底层都是以结构体的形式所实现。
- 在 Swift 中,所有的结构体和枚举类型都是值类型。这意味着它们的实例,以及实例中所包含的任何值类型属 性,在代码中传递的时候都会被复制。
struct Resolution {
var width = 0
var height = 0
}
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
// 在以上示例中,声明了一个名为hd的常量,其值为一个初始化为全高清视频分辨率(1920 像素宽,1080 像 素高)的 Resolution 实例。
然后示例中又声明了一个名为 cinema 的变量,并将 hd 赋值给它。因为 Resolution 是一个结构体,所以 的值其实是 hd 的一个拷贝副本,而不是 hd 本身。尽管 hd 和 cinema 有着相同的宽(width)和高(heigh t),但是在幕后它们是两个完全不同的实例。
//修改
cinema.width = 2000;
print(cinema.width );
//打印结果是:2000
print(hd.width );
//打印结果是: 1920
/*
在将 hd 赋予给 cinema 的时候,实际上是将 hd 中所存储的值进行拷贝,
然后将拷贝的数据存储到新的 cinema 实 例中。
结果就是两个完全独立的实例碰巧包含有相同的数值。
由于两者相互独立,因此将 cinema 的 width 修改为
2048 并不会影响 hd 中的 width 的值。
*/
类型扩展
- 类型扩展的关键字是 extension
extension 要扩展的类型名字 {
}
- 像OC中的分类一样,不过在Swift中只要属于类型没救可以类型扩展
//CGpoint是系统的类型,属于结构体
// 给 CGpoint类扩展一个方法
extension CGPoint {
mutating func moveX(cgX:CGFloat) {
self.x += cgX;
}
}