目录
- 可选链
- 协议的使用1
- 协议的使用2 class static
- 协议的使用3 mutating
- 协议使用4 init
- 协议的使用5 init? init!
- 协议的继承
- 系统提供的协议介绍
- any和anyObject
- 其它总结
- 元数据的应用
可选链
/// 零、可选链
func optionalChain() -> Void {
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 { 18 }
func eat() { print("Person eat") }
subscript(index: Int) -> Int { index }
}
//1、可选项的属性、方法调用
do{
print("--------1--------")
let person: Person? = Person()//可选项
//age
let age1 = person!.age()
print(age1)//18
let age2 = person?.age()
print(age2)//Optional(18)
//dog
let dog1 = person?.dog
print(dog1)//Optional
let dog2 = person!.dog
print(dog2)
//car
let car1 = person?.car
print(car1)//Optional
let car2 = person!.car
print(car2)//Optional
let car3 = person!.car!
print(car3)//Car对象
//如果可选项为nil,调用方法、下标、属性失败,结果为nil
//如果可选项不为nil,调用方法、下标、属性成功,结果会被包装成可选项
//如果结果本来就是可选项,不会进行再次包装
}
//2、
do{
print("----------2---------")
// 多个?可以链接在一起
// 如果链中任何一个节点是nil,那么整个链就会调用失败
let person:Person? = Person()
let dog = person?.dog // Dog?
print(dog)//Optional
let weight = person?.dog.weight // Int?
print(weight)//Optional
//注意car是可选类型
let car = person?.car
let price = person?.car?.price // Int?
print(price)
if let _ = person?.eat() {// ()?
print("eat调用成功")
} else {
print("eat调用失败")
}
if let age = person?.age() {
print("age is ",age)
}else{
print("age 调用失败")
}
}
//3、
do{
print("---------3----------")
var scores = ["Jack": [86, 82, 84], "Rose": [79, 94, 81]]
scores["Jack"]?[0] = 100
scores["Rose"]?[2] += 10
scores["Kate"]?[0] = 88
var num1: Int? = 5
num1? = 10
print(num1)// Optional(10)
var num2: Int? = nil
num2? = 10
print(num2)// nil
}
//4
do{
print("---------4----------")
let dict: [String : (Int, Int) -> Int] = [
"sum" : (+),
"difference" : (-)
]
let result = dict["sum"]?(10, 20)
print(result)// Optional(30), Int?
if let x = result {
print(x)//30
}
}
}
协议的使用1
/// 一、协议的使用1
/**
协议可以用来定义方法、属性、下标的声明,协议可以被枚举、结构体、类遵守(多个协议之间用逗号隔开)
协议中定义方法时不能有默认参数值
默认情况下,协议中定义的内容必须全部都实现
也有办法办到只实现部分内容,以后的课程会讲到
*/
protocol Drawable1{
func draw()
var x:Int{get set}
var y:Int{get}
subscript(index:Int)->Int{get set}
}
func protocolUse1(){
/**
协议中定义属性时必须用var关键字
实现协议时的属性权限要不小于协议中定义的属性权限
协议定义get、set,用var存储属性或get、set计算属性去实现
协议定义get,用任何属性都可以实现
*/
//1、协议实现方式一
do{
print("-------1--------")
class Person : Drawable1 {
var x:Int = 0
let y:Int = 0
func draw() -> Void {
print("Person draw")
}
subscript(index:Int)->Int{
get{ index }
set{ }
}
}
let person = Person()
person.draw()
print(person[0])
}
//2、协议实现方式二
print("-------2--------")
do{
class People:Drawable1{
var x:Int{
get{ 0 }
set{ }
}
var y:Int{
get{ 0 }
}
func draw() -> Void {
print("People draw")
}
subscript(index:Int)->Int{
get { index }
set { }
}
}
let people = People()
people.draw()
print(people[0])
}
}
协议的使用2 class static
// 二、协议的使用2 class static
/**
为了保证通用,协议中必须用static定义类型方法、类型属性、类型下标
*/
protocol Drawable2 {
static func draw()
}
func protocolUse2(){
class Person : Drawable2 {
static func draw () {
print("Person draw")
}
}
class People : Drawable2 {
class func draw() {
print("People draw")
}
}
Person.draw()
People.draw()
}
协议的使用3 mutating
// 三、协议的使用3 mutating
/**
只有将协议中的实例方法标记为mutating
才允许结构体、枚举的具体实现修改自身内存
类在实现方法时不用加mutating,枚举、结构体才需要加mutating
*/
protocol Drawable3 {
mutating func draw()
}
func protocolUse3(){
//
class Person : Drawable3 {
var x : Int = 0
func draw() -> Void {
x = 10
print("Person draw x = ",x)
}
}
//
struct People : Drawable3 {
var x : Int = 0
mutating func draw() -> Void {
x = 10
print("People draw x = ",x)
}
}
let per = Person()
per.draw()
var peo = People()
peo.draw()
}
协议使用4 init
//四、协议使用4 init
/**
协议中还可以定义初始化器init
非final类实现时必须加上required
如果从协议实现的初始化器,刚好是重写了父类的指定初始化器那么这个初始化必须同时加required、override
*/
protocol Drawable4 {
init(x:Int,y:Int)
}
func protocolUse4() -> Void {
//非final类实现时必须加上required
class Person1 : Drawable4 {
required init(x:Int,y:Int) {
print("x is ",x,"y is ",y)
}
}
//final类实现时不必加上required
final class Person2 : Drawable4 {
init(x:Int,y:Int) {
print("x is ",x,"y is ",y)
}
}
class Person {
init(x:Int,y:Int) {
print("x is ",x , "y is ",y)
}
}
//如果从协议实现的初始化器,刚好是重写了父类的指定初始化器那么这个初始化必须同时加required、override
class Student : Person , Drawable4 {
required override init(x:Int,y:Int) {
print("x is ",x ,"y is ",y)
super.init(x: x, y: y)
}
}
}
协议的使用5 init? init!
// 五、协议的使用5 init? init!
/**
协议中定义的init?、init!,可以用init、init?、init!去实现
协议中定义的init,可以用init、init!去实现
*/
protocol Drawable5 {
init()
init?(age:Int)
init!(no:Int)
}
func protocolUse5(){
class Person : Drawable5 {
//协议中定义的init,可以用init、init!去实现
required init() {}
//required init!() {}
//协议中定义的init?、可以用init、init?、init!去实现
required init?(age:Int){}
//required init(age:Int){}
//required init!(age:Int){}
required init!(no:Int){}
//required init(no:Int){}
//required init!(no:Int){}
}
}
协议的继承
/// 六、协议的继承
/**
一个协议可以继承其他协议
*/
protocol Runnable {
func run()
}
protocol Livable : Runnable {
func live()
}
protocol Workable : Runnable {
func work()
}
func protocolInherit() -> Void {
//1、协议的继承
do{
class Person : Livable & Workable{
func work() {
print("Person work")
}
func live() {
print("Person live")
}
func run() {
print("Person run")
}
}
let per = Person()
per.work()//Person work
per.live()//Person live
per.run()//Person run
}
//2、协议的组合
do{
class Animal : Runnable {
func run() {
print("Animal run")
}
}
class Person : Livable {
func live() {
print("Person live")
}
func run() {
print("Person run")
}
}
class People : Livable & Workable{
func work() {
print("People work")
}
func live() {
print("People live")
}
func run() {
print("People run")
}
}
//接收People或其子类实例
func fn0(obj:People){
print("fn0",type(of: obj))
}
fn0(obj: People())//fn0 People
//接收实现了Runable协议的对象
func fn1(obj:Runnable){
print("fn1",type(of: obj))
}
fn1(obj: Animal())//fn1 Animal
fn1(obj: Person())//fn1 Person
fn1(obj: People())//fn1 People
//接收实现了Livable和Workable协议的对象
func fn2(obj:Livable & Workable){
print("fn2",type(of: obj))
}
fn2(obj: People())//fn2 People
//接收实现了Livable和Workable协议并且是People或其子类
func fn3(obj:Livable & Workable & People){
print("fn3",type(of: obj))
}
fn3(obj: People())//fn3 People
}
}
系统提供的协议介绍
/// 七、系统提供的协议介绍
func protocolIntroduceInSystem() -> Void {
//1、枚举的 CaseIterable 让枚举遵守CaseIterable协议,可以实现遍历枚举值
do{
print("---------1----------")
enum Season:CaseIterable{
case spring,summer,autumn,winter
}
let seasons = Season.allCases
print(seasons.count)
for season in seasons {
print(season)
}
}
//2、CustomStringConvertible
do{
print("---------2----------")
/**
遵守CustomStringConvertible、 CustomDebugStringConvertible协议,都可以自定义实例的打印字符串
print调用的是CustomStringConvertible协议的description
debugPrint、po调用的是CustomDebugStringConvertible协议的debugDescription
*/
class Person:CustomStringConvertible & CustomDebugStringConvertible{
var age = 0
var name = "jack"
var description: String{
"age = \(age),name = \(name)"
}
var debugDescription : String {
"debug:age = \(age),name = \(name)"
}
}
print(Person())
debugPrint(Person())
}
}
any和anyObject
/// 八、any和anyObject
protocol anyProtocol:Any{/**该协议任何类型都能遵守*/}
protocol anyObjProtocol:AnyObject{/**该协议只有类类型能遵守*/}
func anyAndAnyObject() -> Void {
/**
Swift提供了2种特殊的类型:Any、AnyObject
Any:可以代表任意类型(枚举、结构体、类,也包括函数类型)
AnyObject:可以代表任意类类型(在协议后面写上: AnyObject代表只有类能遵守这个协议)
在协议后面写上: class也代表只有类能遵守这个协议
*/
class Person{}
class Car{}
//1、any类型
do{
print("---------1--------")
var test:Any = 10
test = Car()
test = [1,2,3]
test = Person()
test = "jack"
print(test)//jack
}
//2、AnyObject类型
do{
print("---------2--------")
var test2:AnyObject = Person()
test2 = Car()
//test2 = LCTest() //struct会报错
test2 = Person()
//test2 = "Tom"
//test2 = 10
print(type(of: test2))//Person
}
//3、
do{
print("---------3--------")
// 创建1个能存放任意类型的数组
let ints:Array<Int> = [1,2,3]
let objs:Array<AnyObject> = [Car(),Person()]
let anys:Array<Any> = [1,2,Car(),"Jeny",Person()]
print(ints,objs,anys,separator:"\n")
//var newAny = Array<Any>()
var newAny = [Any]()
newAny.append(1)
newAny.append("123")
newAny.append(Car())
print(newAny)
}
}
其它总结
/// 九、其它总结
protocol Other11Pro {}
func other11(){
class Car{}
class Person{}
class Student:Person & Other11Pro{
func run() -> Void {
print("Student Run")
}
func study() -> Void {
print("Student Study")
}
}
//1、is用来判断是否为某种类型,as用来做强制类型转换
do{
print("--------1---------")
let a:Int = 10
print(a is Int)//true
print(a is String)//false
let p = Person()
let s = Student()
let c = Car()
print(p is Person)//true
print(s is Student)//true
print(s is Person)//true
print(s is Other11Pro)//true
print(c is Car)//true
print(c is Other11Pro)//false
}
//2、 as as? as!
do{
print("--------2---------")
var stu1:Any = 10
print(stu1 as? Student)//nil
//print(stu as! Student)//对nil解包崩溃
var stu2 = Student()
print(stu2 as? Student)//Optional(Student)
print(stu2 as! Student)//Student
//只有在确定的情况下才能使用as
var stu3:AnyObject = Student()
//let h3 = stu3 as Student
var stu4:Student = Student()
let h4 = stu4 as Any
print(h4)//Student
let d = 10 as Double
print(d)//10.0
}
//3、X.self X.type AnyClass
do{
print("---------3--------")
/**
let p:Person = Person();
p是一个指针,指向一块堆空间内存
这块内存存放着一个对象.
对象类型是Person类型
Person.self是一个指针,指向metadata(存放着类型相关信息)
Person.type是一个类型
Person.self属于Person.Type类型
let metaP:Person.type = Person.self;
metaP是一个指针,指向一块堆空间内存
这块内存存放着一个对象,这个对象叫做元对象
对象类型是Person.type类型
*/
/**
pp变量的内存地址:
(lldb) expression print(Mems.ptr(ofVal: &pp))
0x00007ffeefbff198
pp变量的内存内容
(lldb) memory read/1xg 0x00007ffeefbff198
0x7ffeefbff198: 0x0000000100776280
(lldb) po pp
<Person: 0x100776280>
pp变量指向的堆空间的前 16个字节
(lldb) memory read/2xg 0x100776280
标记1:0x100776280: 0x0000000100050ac0 0x0000000400000002
personType变量的地址
(lldb) expression print(Mems.ptr(ofVal: &personType))
0x00007ffeefbff418
personType变量内存存储内容:
(lldb) memory read/1xg 0x00007ffeefbff418
标记2:0x7ffeefbff418: 0x0000000100050ac0
标记1 与 标记 2 地址相同 证明Person.self 指向元类型
*/
let pp = Person()
print(type(of: pp.self))//Person
let personType:Person.Type = Person.self
print(type(of: personType))//Person.Type
// AnyObject.type 与 AnyClass 相同
let personType1:Person.Type = Person.self
let personType2:AnyObject.Type = Person.self
let personType3:AnyClass = Person.self
print(type(of: personType1))//Person.Type
print(type(of: personType2))//Person.Type
print(type(of: personType3))//Person.Type
//Student.self元类型 同样是 Person.self元类型的子类
//多态:父类指针指向子类对象
var personType4:AnyClass = Person.self
personType4 = Student.self
print(type(of: personType4))//Student.Type
}
do{
print("----------4---------")
class Person {
var age:Int = 18
var height:Int = 180
func grow() -> Void {
print("grow")
}
static func grow()->Void{
print("static grow")
}
}
let per:Person = Person()
per.grow() //grow
per.self.grow() //grow
Person.grow() //static grow
Person.self.grow() //static grow
type(of: per).grow()//static grow
print(Person.self == type(of: per))//true
let perType = type(of: per)
print(perType)//Person
let perTypeType = type(of: perType)
print(perTypeType)//Person.Type
print(type(of: perTypeType))//Person.Type.Type
}
}
元数据的应用
/// 十、元数据的应用
protocol Runnableb {
func test() -> Self
}
func metaDataUse() -> Void {
class Animal { required init() { } }
class Cat : Animal { }
class Dog : Animal { }
class Pig : Animal { }
do{
print("----------1----------")
func create(_ clses: [Animal.Type]) -> [Animal] {
var arr = [Animal]()
for cls in clses {
//cls.init() 与 Cat() 作用相同
arr.append(cls.init())
}
return arr
}
let array:[Animal] = create([Cat.self,Dog.self,Pig.self])
for animal in array {
print(type(of: animal))
}
/**
Cat
Dog
Pig
*/
}
do{
print("----------2----------")
class Person {
var age: Int = 0
}
class Student : Person {
var no: Int = 0
}
print(class_getInstanceSize(Student.self)) // 32
print(class_getSuperclass(Student.self)!) // Person
print(class_getSuperclass(Person.self)!) // Swift._SwiftObject
//从结果可以看得出来,Swift还有个隐藏的基类:Swift._SwiftObject
//可以参考Swift源码:
//https://github.com/apple/swift/blob/master/stdlib/public/runtime/SwiftObject.h
do{
//Self一般用作返回值类型,限定返回值跟方法调用者必须是同一类型(也可以作为参数类型)
class Person : Runnableb {
var age = 0
static var count = 10
required init() { }
func test() -> Self {
print(self.age)
print(Self.count)
//返回一个与调用者相同类型的对象
return type(of: self).init()
}
}
class Student : Person {
}
let p = Person()
print(type(of:p.test()))
let stu = Student()
print(type(of:stu.test()))
/**
0
10
Person
0
10
Student
*/
}
}
}
行者常至,为者常成!