Swift超详细的基础语法-结构体,结构体构造器,定义成员方法, 值类型, 扩充函数
知识点
- 基本概念
- 结构体的基本使用
- 结构体构造器(构造函数/构造方法)
- 结构体扩充函数(方法), 又称成员方法
- 结构体是值类型
1. 基本概念
1.1 概念介绍
结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合
结构体(struct)指的是一种数据结构
结构体是值类型,在方法中传递时是值传递
Swift中的结构体是一类类型, 可以定义属性和函数(甚至构造函数和析构函数等)
结构体的格式
struct 结构体名称 {
结构体属性和函数
}
2. 结构体的基本使用
2.1 Swift要求实例化一个结构体或类的时候,所有的成员变量都必须有初始值
- 如果结构体的属性有默认值, 可以直接使用
结构体名称()实例化一个结构体
// 所有成员属性都有默认值, 直接使用 结构体名称() 实例化结构体
struct Rect {
var width:Double = 0.0 // 结构体所有成员属性都是有初始值
var height:Double = 0.0
}
var r = Rect() // 所以这里可以直接使用 结构体名称() 实例化结构体
print("width = \(r.width) height = \(r.height)")
//输出结果: width = 0.0 height = 0.0
- 如果结构体的属性没有默认值, 必须使用逐一构造器实例化结构体
// 如果结构体的属性没有默认值, 必须使用逐一构造器实例化结构体
struct Rect {
var width : Double
var height : Double
}
// 这里必须使用逐一构造器实例化结构体
var r = Rect(width: 10, height: 20)
print("width = \(r.width) height = \(r.height)")
//输出结果: width = 10.0 height = 20.0
- 结构体属性的访问使用点
.语法
struct Rect {
var width:Double = 0.0
var height:Double = 0.0
}
var r = Rect()
r.width = 100
r.height = 99
print("width = \(r1.width) height = \(r1.height)")
//输出结果: width = 100.0 height = 99.0
- 系统结构体的创建方式
// (CGPoint/CGSize/CGRect)
let point = CGPointMake(100, 100)
let point1 = CGPoint(x: 100, y: 100)
let size = CGSizeMake(100, 100)
let size1 = CGSize(width: 100, height: 100)
let rect = CGRectMake(100, 100, 100, 100)
let rect1 = CGRect(x: 0, y: 0, width: 0, height: 0)
3. 结构体构造器(构造函数/构造方法)
- Swift中的结构体和类跟其它面向对象语言一样都有构造函数, 而OC是没有的
- Swift要求实例化一个结构体或类的时候,所有的成员变量都必须有初始值,
- 构造函数的意义就是用于初始化所有成员变量的, 而不是分配内存, 分配内存是系统帮我们做的.
- 如果结构体中的所有属性都有默认值, 可以使用
结构体名称()实例化一个结构体 - 如果结构体中的属性没有默认值, 可以自定义构造器, 并在构造器中给所有的属性赋值
- 其实结构体有一个默认的逐一构造器, 用于在初始化时给所有属性赋值
3.1 默认的结构体构造器(函数/方法)
struct Rect2 {
var width:Double
var height:Double = 0.0
}
//逐一构造器
var r2 = Rect2(width: 10.0, height: 10.0);
//错误写法, 顺序必须和结构体中成员的顺序一致
var r2 = Rect2(height: 10.0, width: 10.0);
//错误写法, 必须包含所有成员
var r2 = Rect2(height: 10.0);
3.2 扩充结构体的构造器(函数/方法)
- 1.默认情况下实例化结构体时,是在调用系统给结构体的提供的一个默认构造函数
- 2.在一个构造函数执行结束时,是必须保证所有的成员变量都已经被初始化
- 3.如果扩充了构造函数,并且没有明确的实现系统默认的构造函数,那么扩充的构造函数会覆盖系统默认的构造函数
struct Location {
var x : Double
var y : Double
// 由于上面定义结构体属性没有初始化, 所以这个是系统默认的构造函数
init(x : Double, y : Double) { // 明确实现系统默认的构造函数
self.x = x // 这里一定要写上 self , 区分传输参数与成员变量
self.y = y //
}
// 这里扩充了构造函数, 如果没有实现系统默认的构造函数,
// 在使用的时候也将没有系统默认的构造函数, 就只有扩充的构造函数
init(x : String, y : String) { // 扩充的构造函数
self.x = Double(x)!
self.y = Double(y)!
// 这里传入的参数, 转化之后是可选类型, 所以必须解包, 可能转化不成功或者为 nil ,
// 因此会导致程序崩溃, 所以最好做判断后再传解包的值, (这里没有写判断)
}
init() { // 提供通过 结构体名() 实例化出默认的结构体的函数
x = 0 //self.x = 0 // 这里可以不写 self
y = 0 //self.y = 0
}
}
let center = Location()
let center2 = Location(x: 10, y: 10)
let center3 = Location(x: "20", y: "30")
print(center)
print(center2)
print(center3)
// 输出结果:
//Location(x: 0.0, y: 0.0)
//Location(x: 10.0, y: 10.0)
//Location(x: 20.0, y: 30.0)
3.3 "值类型"的构造器代理
- 构造器代理: 构造方法之间的相互调用
- 构造方法可以调用其他构造方法来完成实例的构造, 称之为构造器代理
- 好处: 减少构造方法之间的重复代码
struct Rect1 {
var width:Double
var height:Double
init(width:Double, height:Double){
self.width = width
self.height = height
}
init(){
//width = 0
//height = 0
//构造器代理
self.init(width:0 , height:0)
}
func show(){
print("width = \(width) height = \(height)")
}
}
var r2 = Rect1()
r2.show()
//输出结果: width = 0.0 height = 0.0
var r3 = Rect1(width: 100, height: 100)
r3.show()
//输出结果: width = 100.0 height = 100.0
4. 结构体扩充函数(方法), 又称成员方法
- 在C和OC中结构体只有属性, 而Swift中结构体中还可以定义函数(方法)
4.1 给自定义的结构体扩充函数
- 给自定义的结构体扩充函数,必须在函数前加
mutating - 给结构体定义一个函数, 该函数只属于该结构体
- 结构体中的成员函数必须使用某个实例调用
- 结构体内部函数可以访问成员属性
struct Location {
var x : Double
var y : Double
// 给结构体扩充函数,必须在函数前加 mutating
mutating func moveH(distance : Double) {
x += distance
}
mutating func moveV(distance : Double) {
y += distance
}
mutating func test() {
print("test")
}
}
var center = Location(x: 100, y: 100)
center.moveH(100)
center.moveV(-100)
print(center)
4.2 给系统的结构体扩充方法
- 必须在系统提供结构体类型前加上
extension
extension CGPoint {
mutating func moveH(distance : CGFloat) {
x += distance
}
}
var point = CGPoint(x: 100, y: 100)
point.moveH(50)
print(point)
4.3 (补充) 给系统的类扩充方法
- 使用系统提供的方法
let btn = UIButton()
btn.setTitle("按钮", forState: .Normal)
let title = btn.titleLabel!.text
- 给系统的提供的类添加方法, 必须在类名前加上
extension关键字
extension UIButton {
func getTitle() -> String? {
return self.titleLabel!.text
}
}
let title1 = btn.getTitle()
5. 结构体是值类型
5.1 结构体变量或常量赋值是值拷贝
- 结构体是值类型, 结构体之间的赋值其实是将等号
=右边的结构体中的值完全拷贝一份到等号=左边的变量或常量 - 所以结构体间相互赋值是两个不同的实例, 是值拷贝拷贝
struct Rect4 {
var width:Double
var height:Double = 0.0
func show() -> Void{
print("width = \(width) height = \(height)")
}
}
var r5 = Rect4(width: 10.0, height: 10.0)
var r6 = r5
r5.show()
r6.show()
r5.width = 20.0
r5.show()
r6.show()
//输出结果:
//width = 10.0 height = 10.0
//width = 10.0 height = 10.0
//width = 20.0 height = 10.0
//width = 10.0 height = 10.0
5.2 结构体常量与存储属性的关系
- 结构体和枚举是值类型
- 因此不能修改结构体常量中的属性
- 不能修改结构体/枚举常量对象中的值, 因为他指向的对象是一个常量
struct Person2 {
var name: String
var age: Int
}
let p2: Person2 = Person2(name: "cdh", age: 20)
//因为结构体是值类型, 所以不能修改结构体常量中的属性
//不能修改结构体/枚举常量对象中的值, 因为他指向的对象是一个常量
//以下写法错误
//p2.name = "CDH" //不能修改结构体常量对象的值
//以下写法错误
//p2 = Person2(name: "CDH", age: 50)
5.3 (补充)类常量与存储属性的关系
- 类是引用类型
- 可以修改类常量中属性的值, 因为他指向的对象不是一个常量
class Person3 {
var name: String = "cdh"
var age: Int = 20
}
let p3:Person3 = Person3()
//可以修改类常量中属性的值, 因为他指向的对象不是一个常量
p3.name = "CDH"
//不可以修改类常量的指向
//以下写法是错误的
//p3 = Person4()
Swift超详细的基础语法-结构体,结构体构造器,定义成员方法, 值类型, 扩充函数的更多相关文章
- Swift与C#的基础语法比较
背景: 这两天不小心看了一下Swift的基础语法,感觉既然看了,还是写一下笔记,留个痕迹~ 总体而言,感觉Swift是一种前后端多种语言混合的产物~~~ 做为一名.NET阵营人士,少少多多总喜欢通过对 ...
- 【Day1】4.基础语法及分支结构
视频地址(全部) https://edu.csdn.net/course/detail/26057 课件地址(全部) https://download.csdn.net/download/gentl ...
- 3、二、c# 面向对像编程。类,结构、C# 数据类型(引用类型、值 类型、指针类型)、ref参数与out参数、方法的重载、静态类型与静态成员、继承与多态、委托与事件
一.类 定义类使用class关键字. <access specifier> class class_name { // member variables 成员变量 <access s ...
- 超详细Java基础-多态
茫茫人海千千万万,感谢这一秒你看到这里.希望我的能对你的有所帮助!共勉! 愿你在未来的日子,保持热爱,奔赴山海! Java基础知识(多态) 多态 多态就是指程序中定义的引用变量所指向的具体类型和通过该 ...
- 超详细“零”基础kafka入门篇
1.认识kafka 1.1 kafka简介 Kafka 是一个分布式流媒体平台 kafka官网:http://kafka.apache.org/ (1)流媒体平台有三个关键功能: 发布和订阅记录流,类 ...
- Swift - 34 - 闭包的基础语法
//: Playground - noun: a place where people can play import UIKit // 初始化一个整数数组 var arr = [1, 3, 5, 7 ...
- 八皇后问题 递归实现 C语言 超详细 思路 基础
八皇后问题 :假设 將八个皇后放到国际象棋盘上,使其两两之间无法相互攻击.共有几种摆法? 基础知识: 国际象棋里,棋盘为8X8格. 皇后每步可以沿直线.斜线 走任意格. 思路: 1.想把8个皇后放进去 ...
- Python基础语法-内置数据结构之列表
列表的一些特点: 列表是最常用的线性数据结构 list是一系列元素的有序组合 list是可变的 列表的操作, 增:append.extend.insert 删:clear.pop.remove 改:r ...
- Python基础语法04-数据结构
Python Number(数字) Python Number 数据类型用于存储数值. 数据类型是不允许改变的,这就意味着如果改变 Number 数据类型的值,将重新分配内存空间. Python 支持 ...
随机推荐
- NGINX(一)内存结构
ngx_buf_t和ngx_chain_t是nginx中操作内存的重要手段, 很多的数据都需要通过这个结构进行保存. 其中ngx_buf_t中保存一块可用内存, ngx_chain_t则是将内存块连接 ...
- redis-3.0.0集群的安装及使用
redis集群需要至少6个节点(偶数节点),3个主节点,3个从节点.注意:集群模式最好不要keys *查询数据. 1 下载redis,官网下载3.0.0版本,之前2.几的版本不支持集群模式.下载地址: ...
- 设计模式_Mediator_调停者模式
形象例子: 四个MM打麻将,相互之间谁应该给谁多少钱算不清楚了,幸亏当时我在旁边,按照各自的筹码数算钱,赚了钱的从我这里拿,赔了钱的也付给我,一切就OK啦,俺得到了四个MM的电话.调停者模式: 调停者 ...
- Ajax解决缓存的5种方法
原文:http://www.ido321.com/129.html 1.在ajax发送请求前加上 anyAjaxObj.setRequestHeader(“If-Modified-Since”,”0″ ...
- 【暑假】[深入动态规划]UVa 1628 Pizza Delivery
UVa 1628 Pizza Delivery 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=51189 思路: ...
- UMA - Unity Multipurpose Avatar
UMA - Unity Multipurpose Avatar UMA version 1.0.1.0R Unity 4.3 What is UMA? UMA - Unity Multipurpose ...
- Java Script after Douglas Crockford's Training (JSON father)
有幸能参加大牛的培训,学到了很多东西,下面总结一下: 1.总的思想是每一门语言都有好有坏,我们要通过好的代码规范和其他一些方式去避免使用糟糠的那一部分.JS有很多缺点,但是也有很多优点,我们就用他的优 ...
- JAVA一个关于传递引用的测试
以下测试主要为了说明:对传递对象或传递引用进行修改,对最终值的影响情况 public class PassTest { @Before public void setUp() thro ...
- JDBC 的基本步骤
JDBC 的基本步骤: 一.导入mysql-connector-java-x.x.x-bin.jar后: 二.代码 1. 注册驱动(三种方式)2. 创建一个连接对象(三种方式) 3. 创建一个sql语 ...
- DTD Tutorial
The purpose of a DTD (Document Type Definition) is to define the legal building blocks of an XML doc ...