可选链 Optional Chaining
class Car {
var price = 0
}
class Dog {
var weight = 0
}
class Person {
var name: String = ""
var dog: Dog = Dog()
var car: Car? = Car()
func age() -> Int {
return 18
}
func eat() {
print("Person eat")
}
subscript(index: Int) -> Int {
return index
}
}
var person: Person? = Person()
/*
会先检查person是否为nil
如果是nil 后面的就不会执行 直接返回nil
如果不是nil 那就解包 调用
*/
person?.age()
var name = person?.name
var index = person?[6]
- 如果可选项为nil 调用方法 下标 属性失败 结果为nil
- 如果可选项不为nil 调用放法 下标 属性成功 结果会被包装成可选项
- 如果结果本来就是可选项 不会进行再次包装
if let _ = person?.eat(){
print("eat 调用成功")
}else{
print("eat 调用失败")
}
var scores = ["jack" : [86,82,84], "Rose" : [79,94,81]]
var array = scores["jack"]
array?[0]
var num1: Int? = 5
//num1加上? 会判断包装里面是否为空 如果不为空 就会继续赋值
num1? = 10// 10
var num2: Int? = nil
//num2为空 就不会继续赋值
num2? = 10//nil
var dict: [String : (Int, Int) -> Int] = [
"sum" : (+),
"difference" : (-)
]
var result = dict["sum"]?(10,20)
//dict["sum"] 如果取出来是空的 后面就不会再执行了
print(result)
Optional(30)
协议
协议可以用来定义方法 属性 下标的声明 协议可以被枚举 结构体 类遵守(多个协议之间用,隔开)
- 协议中定义方法时不能有默认参数值
- 默认情况下 协议中定义的内存必须全部都实现
协议中的属性
不要求是存储属性还是计算属性 实现就行
- 协议中定义属性必须是用var关键字
- 实现协议时的属性权限要不小于协议中定义的属性权限
a.协议定义get set 用var存储属性或者get set计算属性去实现
b.协议定义get 用任何属性都可以实现
protocol Drawable {
func draw()
var x: Int { get set}
var y: Int { get }
subscript(index: Int) -> Int{
get
set
}
}
class Person: Drawable {
var x: Int = 0
var y: Int = 0
func draw() {
print("person draw")
}
subscript(index: Int) -> Int{
get{ return index }
set{ }
}
}
protocol Drawable {
func draw()
var x: Int { get set}
var y: Int { get }
subscript(index: Int) -> Int{
get
set
}
}
class Person: Drawable {
var x: Int {
get { return 0 }
set { }
}
var y: Int {
get { return 0}
}
func draw() {
print("person draw")
}
subscript(index: Int) -> Int{
get{ return index }
set{ }
}
}
static class
为了保证通用 协议中必须用static定义类型方法 类型属性 类型下标
protocol Drawable {
static func draw()
}
class Person: Drawable {
class func draw() {
<#code#>
}
}
mutating
只有将协议中的实例方法标记为mutating
- 才允许结构体 枚举的具体实现修改自身内存
- 类在实现方法时不用加mutating
枚举 结构体才需要加mutating
init
协议中还可以订阅初始化器init
非final类实现时必须加上required
final类不能被继承重写
要求所有遵守这个协议的类都必须有这个初始化器
如果从协议实现的初始化器 刚好是重写了父类的指定初始化器
那么这个初始化器必须同时加required override
protocol Drawable {
init(age: Int)
}
class Person {
init(age: Int) {
}
}
class Student: Person, Drawable {
required override init(age: Int) {
super.init(age: 0)
}
}
init init?init!
协议中定义的init? init! 可以用init init?init!去实现
协议中定义的init 可以用init init!去实现
实现方式.png
协议的继承
一个协议可以继承其他协议
protocol Runnable {
func run()
}
protocol Livable: Runnable {
func breath()
}
class Person: Livable {
func run() {
<#code#>
}
func breath() {
}
}
协议组合
//接受Person或者其子类的实例
func fn0(obj: Person){}
//接受遵守Livable协议的实例
func fn1(obj: Livable){}
//接受同时遵守Livable Runnable协议的实例
func fn2(obj: Livable & Runnable){}
//接受同时遵守Livable Runnable协议 并且是Person或者其子类的实例
func fn3(obj: Livable & Runnable & Person){}
协议组合 可以包含一个类类型(最多一个)
typealias RealPerson = Livable & Runnable & Person
func fn4(obj: RealPerson){}
CaseIterable
让枚举遵守CaseIterable 协议 可实现遍历枚举值
enum Seasion: CaseIterable {
case spring, summer,automn,winter
}
let seasions = Seasion.allCases
for seasion in seasions {
print(seasion)
}
CustomSpringConvertible
遵守CustomSpringConvertible协议 可以自定义实例的打印字符串
class Person: CustomStringConvertible {
var age: Int
var name: String
init(age: Int, name: String) {
self.age = age
self.name = name
}
var description: String {
return "age=\(age),name=\(name)"
}
}
var p = Person(age: 10, name: "Jack")
print(p)
age = 10 name = "Jack"
Any AnyObject
Any 可以代表任何类型(枚举 结构体 类 也包括函数类型)
AnyObject 可以代表任意类类型
如果在协议后面写上AnyObject 代表这个协议只能是类来遵守
var data = [Any]()
data.append(1)
data.append("2")
data.append(23.44)
is as? as! as
is 用来判断是否为某种类型 as用来强制类型转换
protocol Runnable {
func run()
}
class Person {
}
class Student: Person,Runnable {
func run() {
print("run")
}
func study() {
print("study")
}
}
var stu: Any = 10
print(stu is Int)
stu = "Jack"
print(stu is String)
stu = Student()
print(stu is Person)
print(stu is Student)
print(stu is Runnable)
true
true
true
true
true
(stu as? Student)?.study()
没有调用study()
var data = [Any]()
data.append(Int("123") as Any)
X.self X.Type AnyClass
X.self 是一个元类型(metadata)的指针 metadata存放着类型相关信息
X.self属于X.type 类型
var p = Person()
var pType: Person.Type = Person.self
var p = Person()
var pType: Person.Type = Person.self
var stuType: Student.Type = Student.self
pType = Student.self
var perType = type(of: p)
元类型的应用
class Animal {
required init() {
}
}
class Cat: Animal { }
class Dog: Animal {
}
class Pig: Animal {
}
func create(_ clses: [Animal.Type]) -> [Animal] {
var arr = [Animal]()
for cls in clses {
arr.append(cls.init())
}
return arr
}
print(create([Cat.self,Dog.self,Pig.self]))
[swiftTest.Cat, swiftTest.Dog, swiftTest.Pig]
为了保证子类一定有init 所以 要用required
Self
Self 一般用作返回值类型 限定返回值跟方法调用者必须是统一类型(也可以作为参数类型)
protocol Runnable {
func test() -> Self
}
class Person: Runnable {
required init() {}
func test() -> Self {
return type(of: self).init()
}
}
如果Self用在类中 要求返回时调用的初始化器是required 的
网友评论