一、与声明有关的关键字
class Person: NSObject {
//声明一个实例方法
func run() {
print("run")
}
//class修饰表示:声明一个类方法
class func work() {
print("work")
}
}
复制代码
//声明:
struct Person {
var name:String
var age:Int
func introduce(){
print("我叫:\(name),今年\(age)岁")
}
}
//调用:
var person = Person(name: "xiaoMing",age: 20)
person.introduce()
//输出:
我叫:xiaoMing,今年20岁
复制代码
struct
和 class
比较
struct是结构体,class是类
1、struct是值类型,class是引用类型;意思是:声明一个新的变量指向这个结构体,改变某个属性,原本的结构体属性不会发生变化;而类会随着改变
`
代码示例:
struct myStru {
var width = 200
}
class myClass {
var width = 200
}
//调用
var stu = myStru()
var stu2 = stu
stu2.width = 300
print(stu.width,stu2.width)
//200 300
var cls = myClass()
var cls2 = cls
cls2.width = 300
print(cls.width,cls2.width)
//300 300
`
2、struct不能被继承,class可以被继承
3、用let修饰class对象,能够修改类的值;若要修改struct的值,要用var来修饰
4、struct是放在栈上,class是放在堆上,因此struct的访问速度更快
5、struct里面如果想声明一个func来修改声明的属性,需要添加关键字mutating,才能编译成功;而class不需要
6、所有的struct都有一个自动生成的成员构造器,而class需要自己生成
7、在struct中,成员变量可以没有初始值;但在class中,如果成员变量没有初始值,就必须为它写一个构造函数
复制代码
class Person: NSObject {
var name: String
//类方法,并且该方法不能被子类重写
static func run() {
print(self.name + "running")
}
}
复制代码
static
和 class
比较
都是放在`func`前面用于指定类方法,只不过`static`修饰的类方法不可以被重写
复制代码
typealias
:各类起别名
//声明
typealias abc = Int
//调用
let a:abc = 100
复制代码
//写法1,默认赋值0、1、2、3
enum Orientation1:Int{
case East
case South
case West
case north
}
//写法2
enum Orientation2:Int{
case East,South,West,north
}
//调用 具体的值
print(Orientation1.East.rawValue,Orientation1.south.rawValue,Orientation2.West.rawValue,Orientation2.north.rawValue)
//打印
0 1 2 3
复制代码
//给person类添加一个run方法
class Person: NSObject {
var name = "swift"
}
extension Person{
func run() {
print(self.name + "running")
}
}
//调用
let per = Person()
per.run()
复制代码
struct Person {
var age = 0
var no = 0
subscript(index: Int) -> Int {
set {
if index == 0 {
age = newValue
} else {
no = newValue
}
}
get {
if index == 0 {
return age
} else {
return no
}
}
}
}
var p = Person()
p[0] = 10
p[1] = 20
print(p.age) // 10
print(p[0]) // 10
print(p.no) // 20
print(p[1]) // 20
复制代码
传多个参数的例子:
class Matix {
var data = [
[0,0,0],
[0,0,0],
[0,0,0]
]
subscript(row: Int , col: Int) -> Int {
set {
//守卫,不在这个范围之内的就return
guard row >= 0 && row < 3 && col >= 0 && col < 3 else {
return
}
data[row][col] = newValue
}
get {
guard row >= 0 && row < 3 && col >= 0 && col < 3 else {
return 0
}
return data[row][col]
}
}
}
//调用
var m = Matix()
m[1, 1] = 3
m[0, 1] = 4
//这个超出范围,直接return了
m[4, 4] = 9
print(m.data)
//打印
[[0, 4, 0], [0, 3, 0], [0, 0, 0]]
复制代码
class PerSon: NSObject {
//如果不给属性直接赋一个初始化值,就必须声明构造函数
var name:String
init(name : String) {
self.name = name
}
}
//调用
let person = PerSon.init(name: "xiaoMing")
print(person.name)
//简写
let per = PerSon(name: "xiaoHong")
print(per.name)
复制代码
二、与语句有关的关键字
fallthrough
:穿透,在switch中,执行完当前case,继续向下执行下一个case
//写法1 = 写法2
let num = 100
//写法1
switch num {
case 100:
fallthrough
case 200:
print("100 + 200")
default:
print("no")
}
//写法2
switch num {
case 100,200:
print("100 + 200")
default:
print("no")
}
复制代码
where
:筛选条件用的,适用于do-catch
、switch
、for-in
、泛型
、协议
等
let array = [100,-50,36,-8,45]
//遍历数组,只有值大于40的才打印
for i in array where i > 40 {
print(i)
}
//打印
100
45
复制代码
三、与表达式和类型有关的关键字
// 1.定义数组
let array : [Any] = [12, "zhangsan"]
// 2.取出数组中的第一个
let objcFirst = array.first!
// 3.判断第一个元素是否是一个Int类型
if objcFirst is Int {
print("是Int类型")
} else {
print("非Int类型")
}
复制代码
as
:类型转换操作符,向上转型,从派生类转换成基类
//本身根据值定义的是int类型,通过as转换成float类型
var number = 1 as Float
print(number) //1.0
var number = 1 as Float
相当于
var number = Float(1)
复制代码
-
as!
:向下转型,转成其子类类型,属于强制转型,如果转换失败会报错 -
as?
:规则跟as!
一样,如果转换失败,会返回一个nil对象
// 1.定义数组
let array : [Any] = [12, "zhangsan"]
// 2.取出数组中最后一个元素
let objcLast = array.last!
// 3.转成真正的类型来使用
// as? 将Any转成可选类型,通过判断可选类型是否有值,来决定是否转化成功了
let name = objcLast as? String
print(name) // 结果:Optional("zhangsan")
// as! 将Any转成具体的类型,如果不是该类型,那么程序会崩溃
let name2 = objcLast as! String
print(name2) // 结果:zhangsan
复制代码
四、特定上下文中的关键字
/*
对系统的init进行扩充,
并且这个方法是公共的,
如果子类要修改,就需要先实现父类方法,不能直接重写
*/
required convenience public init(...) {
...
self.init()
...
}
复制代码
使用规则:
- 只能用于修饰类初始化方法
- 如果子类初始化方法的参数异于父类,要先实现父类的
required init
方法,这时不能用override
,要同样使用required
修饰 - 如果子类没有init方法,就不用实现父类的
required init
方法
//子类异于父类init方法情况
class PerSon: NSObject {
var name: String
//如果子类要自定义init方法,要先实现父类的
required init(name: String) {
self.name = name
}
}
class Student: PerSon {
var age: Int = 0
//先实现父类的
required init(name:String) {
super.init(name: name)
}
//再进行自定义init
init(firstName: String, age:Int) {
self.age = age
super.init(name: firstName)
}
}
复制代码
//正常情况
struct myStruct1 {
var num1 = 100
var num2 = 200
var num3 = 300
}
var stu1 = myStruct1()
print(stu1.num1)//100
//直接修改成员变量的值
stu1.num1 = 999
print(stu1.num1)//999
//通过内部方法改变值
struct myStruct2 {
var num1 = 100
var num2 = 200
var num3 = 300
mutating func changeNum(mark:Int) {
self.num1 += mark
}
}
//调用
var stu2 = myStruct2()
print(stu2.num1)//100
//通过调用结构体的成员方法来修改成员变量的值
stu2.changeNum(mark: 99)
print(stu2.num1)//199
复制代码
lazy
:懒加载,修饰变量,只有在第一次调用的时候才去初始化值
lazy var first = NSArray(objects: "1","2")
复制代码
-
final
:可以用来修饰class
、func
、var
,表示不可重写。可以将类或者类中的部分实现保护起来,从而避免子类破坏 -
inout
:将值类型的对象 用 引用的方式传递,意思是可以修改外部变量
func test(num: inout Int){
//如果不加inout,改变外部变量会报错
num += 1
}
var a = 10
//调用的时候,是取地址操作
test(num: &a)
print(a)//11
复制代码
func test(){
print("函数开始")
defer{
print("执行defer1")
}
print("函数将结束")
defer{
print("执行defer2")
}
defer{
print("执行defer3")
}
}
//调用
test()
//打印
函数开始
函数将结束
执行defer3
执行defer2
执行defer1
复制代码
添加异步线程的情况
func test(){
print("函数开始")
defer{
print("执行defer1")
}
defer{
print("执行defer2")
}
dispatchQueue.main.asyncAfter(deadline: .Now()+1) {
print("异步执行完毕")
}
print("函数将结束")
defer{
print("执行defer3")
}
}
test()
//打印:
函数开始
函数将结束
执行defer3
执行defer2
执行defer1
异步执行完毕
结论:
异步代码的执行,不会影响defer的执行时间。事实上,defer的执行只和其所在的作用域有关,如果作用域即将被回收,那么会在回收之前执行defer。
复制代码
代码示例:
//错误类型枚举
enum MyError : Error {
case ErrorOne
case ErrorTwo
case ErrorOther
}
//使用:关键字所在的位置
func thisFuncCouldThrowError(_ type: Int) throws -> String{
if type == 1 {
return "成功"
}else if type == 2{
throw MyError.ErrorTwo
}else{
throw MyError.ErrorOther
}
}
//调用,配合do-catch进行异常捕捉,抛出异常的方法在调用前要加 try 关键字
do {
let stu = try thisFuncCouldThrowError(20)
print("如果出现错误,这里的代码就不会执行了")
print(stu)
} catch let err as MyError/* 这里如果捕捉到的错误,属于自定义枚举的值,就进行相关处理*/{
print("出现了错误")
print(err)
} catch {
//这里必须要携带一个空的catch 不然会报错。 原因是可能遗漏
}
//打印
出现了错误
ErrorOther
复制代码
rethrows
:异常往上传递的关键字,针对的不是函数或者方法的本身,而是它携带的闭包类型的参数,当它的闭包类型的参数throws的时候,我们要使用rethrows继续将这个异常往上传递, 直到被调用者使用到。这相比throws多一个传递的环节
//throw函数作为闭包参数传入
//throws
func thisFuncCouldThrowError(_ type: Int) throws -> String{
if type == 1 {
return "成功"
}else if type == 2{
throw MyError.ErrorTwo
}else{
throw MyError.ErrorOther
}
}
//rethrows
func thisFuncRethrows(_ throwsError:(Int) throws -> String) rethrows{
do {
let stu = try throwsError(20)
print("如果出现错误,这里的代码就不会执行了")
print(stu)
} catch let err as MyError{
throw err //这里进行了 再次throw
} catch{
}
}
//调用
let afunc = self.thisFuncCouldThrowError
do {
try self.thisFuncRethrows(afunc)
print("没有错误,如果出现错误,这里的代码就不会执行了")
} catch let err as MyError {
print("出现了错误")
print(err)
}catch{
//这里必须要携带一个空的catch 不然会报错。 原因是可能遗漏
}
复制代码
五、访问权限关键字
swift中提供了5种访问控制的权限: 由低到高:private
、fileprivate
、internal
、public
、open
private
:只能在当前类class中访问、extension修饰的拓展类中可以访问,但是子类及其他类不可访问fileprivate
:只能在当前源文件中访问。也就是说不同文件中的子类也无法访问internal
:默认的访问级别。在源代码所在的整个模块都可以被访问public
:可以被任何人访问,在本模块中可以被override(重写)和继承,但在其他的模块中不可以被override和继承open
:可以被任何人使用,包含override和继承
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。