Swift_学习笔记_类

类的声明和定义

  • 类在定义时,可以带默认值也可以不带。
  • 类的创建有无参数均可。
  • 类的属性访问,采用点语法。

类的相互引用

  • 类之间可以相互引用,注意循环引用的问题
// 存在循环引用的问题
class BankCard{
     var user:User
}
class User{
     var bankCard:BankCard
}

解决循环引用:
在实例的生命周期中,如果某些时候引用没有值,那么弱引用可以避免循环强引用。如果引用总是有值,则可以使用无主引用。
1. 弱引用,使用 weak 修饰
- 注意弱引用必须被声明为变量,表明其值能在运行时被修改。
- 弱引用不能被声明为常量。
- 弱引用不会保持所引用的实例,即使引用存在,实例也有可能被销毁。因此,ARC 会在引用的实例被销毁后自动将其赋值为nil。
- 弱引用可以没有值,你必须将每一个弱引用声明为可选类型
2. 无主引用,使用 unowned 修饰
- 可以在声明属性或者变量时,在前面加上关键字unowned
- 无主引用是非可选类型,你不需要在使用它的时候将它展开。无主引用总是可以被直接访问。
- ARC 无法在实例被销毁后将无主引用设为nil,因为非可选类型的变量不允许被赋值为nil,因为非可选类型的变量不允许被赋值为nil。
- 注意如果你试图在实例被销毁后,访问该实例的无主引用,会触发运行时错误。使用无主引用,你必须确保引用始终指向一个未销毁的实例。还需要注意的是如果你试图访问实例已经被销毁的无主引用,Swift 确保程序会直接崩溃,而不会发生无法预期的行为。所以你应当避免这样的事情发生。

类的嵌套

  • 可以在一个类中声明另一个类
  • 两个不同的类,可以在其内部声明相同的类
class IOS{
    class Student {
        var name = ""
    }
}
class Android{
    class Student {
        var name = ""
    }
}
var stu1 = IOS.Student()
var stu2 = Android.Student()
// stu1/stu2是两个不同的对象

类是引用类型

  • 类是引用类型,类的赋值也是指针的赋值,指向的依旧是同一片内存空间。
class IOS{
    class Student {
        var name = ""
    }
}

var stu1 = IOS.Student()
stu1.name = "Li"
var stu2 = stu1
stu2.name = "wang"

print(stu1.name) // wang

恒等操作符(===/!===)

  • 判断两个对象是否指向同一片内存空间,返回值为布尔值
class IOS{
    class Student {
        var name = ""
    }
}
class Android{
    class Student {
        var name = ""
    }
}
var stu1 = IOS.Student()
var stu2 = Android.Student()
print(stu1 === stu2) // false

类的哈希

  • 由于字典的key值必须可以被哈希化,如果将类作为字典的key值属性类型,且类没有继承自NSObject,即将类的对象作为字典的key值,此时必须实现hash方法。
  • 如果类继承自NSObject,则不需要进行hash化,因为根类内存在hash化方法。
class IOS:NSObject{
//    override class func hash() ->Int {
//        return "hello".hash
//    }
}
var ios1 = IOS()
var ios2 = IOS()

var dict:Dictionary<IOS,String> = [ios1:"hello",ios2:"hi"]

集合类型对象之间的赋值和拷贝

字典的赋值和拷贝

  • 字典的key值或者Value值如果其类型为引用类型,则不会进行拷贝。
  • 如果key/value均不是引用类型,则都进行拷贝。

数组的赋值和拷贝

  • 经过测试,数组的赋值都经过了值拷贝。

属性

  • 类可以定义三种属性:对象属性、计算属性和类属性

对象属性

常量属性

  • 常量属性值为基本数据类型时,不可以在对象创建后更改。
  • 常量属性为结构体或者枚举类型时,不可以在对象创建后更改,包括结构体或者枚举内的值。
struct Class {
    var numberOfPerson = 100
}
class Student{
    let classInfo = Class()
}
var stu = Student()
stu.classInfo.numberOfPerson = 200 // 不可以更改
stu.classInfo = Class() // 不可以更改
  • 常量属性为引用类型时,可以更改引用类型内的属性值,而不可以更改该常量属性。
class Class {
    var numberOfPerson = 100
}
class Student{
    let classInfo = Class()
}
var stu = Student()
stu.classInfo.numberOfPerson = 200
print(stu.classInfo.numberOfPerson) // 200(可以更改)
stu.classInfo = Class() // 不可以更改

常量属性的赋值方法

  • 结构体的常量属性需要在初始化时进行赋值
  • 类的常量属性,由于没有构造方法,需要自己实现构造方法。
class Student{
    let name:String
    let age:Int
    init(name:String,age:Int) {
        self.name = name
        self.age = age
    }
}
var stu = Student(name: "wang", age: 28)
print(stu.name) // wang

变量属性

  • 变量属性可以在任何时候进行修改

懒加载

  • 懒加载又称延迟加载,只有正式使用时才使用某个属性的时候,才会进行加载。
  • 懒加载关键字:lazy
class CityInfo{
    init() {
        sleep(10)
    }
}
class Metro{
    var name:String?
    lazy var city = CityInfo()
}
var line1 = Metro()
line1.name = "一号线"
print(line1.name!) // 一号线
var city = line1.city
print("加载城市信息") // 输出“一号线” 10秒后输出本语句

监测属性值得变化

  • 利用willSet和didSet对属性值进行观察
  • willSet内存在新属性值:newValue
  • didSet内存在旧属性值:oldValue
class LoginUser{
    init(name:String) {
        self.name = name
    }
    var name:String{
        willSet{
            print("新值:\(newValue)")
        }
        didSet{
            print("旧值:\(oldValue)")
        }
    }
}
var user = LoginUser(name: "wang")
/* 使用初始化方法,不会调用属性值观察
  对属性值进行修改,将会调用属性值观察
 */
 user.name = "Li"
 // 新值:Li
// 值:wang

运算属性

  • 运算属性需要重写set和get方法;
  • 如果重写set,则必须重写get;
  • 如果只重写get,则该属性值只读;
  • 运算属性不能用来存储数值,更多的是用来进行逻辑处理,并对其它的存储属性值进行修改。
class Square{
// 存储属性值
    var width = 0
    // 运算属性值
    var round:Int{
        get{
            return width * 4
        }
        set{
            width = newValue/4
        }
    }
}
var square = Square()
square.round = 40
print(square.width) // 10

类属性

  • 类属性不依赖与具体的实例,是属性类的共有属性
  • 命名类属性需要关键字:static
class ClassRoom{
    static var maxOfNumber = 10
}
print(ClassRoom.maxOfNumber) // 10

方法

对象方法

类方法

  • 类方法声明,需要在方法名前添加关键字 class
  • 类方法调用,用类名直接调用
class Tool{
    class func share (){
        print("开始分享")
    }
}
Tool.share()
  • 类方法实现单利设计模式
class Tool{
    var toolName = ""
    struct ToolParmars {
        static var tool:Tool? = nil
    }
    class func sharedTool() -> Tool {
        if (ToolParmars.tool == nil) {
            ToolParmars.tool = Tool()
        }
        return ToolParmars.tool!
    }
}

var tool = Tool.sharedTool()
tool.toolName = "图片"
var tool2 = Tool.sharedTool()
print(tool2.toolName) // 图片

subscript下标

subscript的作用

  • Swift提供的快捷访问对象属性的方法。
  • subscript的使用方式与数组及字典对元素的访问方式类似。

subscript的声明

  • 声明需要关键字:subscript
class TestClass{
    var testDict = Dictionary<Int,String>()
    subscript(index:Int)->String{
        get{
            return testDict[index]!
        }
        set{
            testDict[index] = newValue
        }
    }
}
var test = TestClass()
test[2] = "hello"
test[12] = "world"
print(test.testDict)
// [2: "hello", 12: "world"]

subscript的使用

  • 使用test[2]表示访问subscript(2),调用里面的set和get方法

subscript的使用方法的例子

// 学生类
class Student{
    var name = ""
    var stuId = 0
    init(name:String,stuId:Int) {
        self.name = name
        self.stuId = stuId
    }
}
// 班级类
class ClassRoom{
    var className = ""
    // 学生字典
    var students = Dictionary<Int,Student>()
    init(className:String) {
        self.className = className
    }
    subscript(stuId:Int)->Student{
        get{
            return students[stuId]!
        }
        set {
            students[stuId] = newValue
        }
    }
}
// 学校类
class School{
    // 班级字典
    var classes = Dictionary<Int,ClassRoom>()
    // 根据班级、学号查找学生
    subscript(classId:Int,stuId:Int) -> Student{
        get{
            var cr:ClassRoom? = classes[classId]
            var stu:Student? = cr![stuId]
            return stu!
        }
        set{
            var cr:ClassRoom? = classes[classId]
            cr![stuId] = newValue

        }
    }
    // 根据班号查找班级
    subscript(classId:Int) -> ClassRoom{
        get{
            return classes[classId]!
        }
        set{
            classes[classId] = newValue
        }
    }

}
var phone100 = School()
// 对学校内所有的班级
for classId in 1...20 {
    // 利用班级的初始化方法进行初始化
    var classRoom = ClassRoom(className: "班级:\(classId)")
    // 对每个班的学生进行初始化
    for stuId in 1...139 {
        // 利用学生的初始化方法进行初始化
        var stu = Student(name: "班级:\(classId) - 学生\(stuId)", stuId: stuId)
        classRoom[stuId] = stu
    }
    phone100[classId] = classRoom
}
print(phone100[10,130].name)

var maxNumberOfProvice = 300
var maxNumberOfCity = 40
// 城市类
class City{
    var cityName:String!
    var cityNumber:Int!
    init(cityName:String,cityNumber:Int) {
        self.cityName = cityName
        self.cityNumber = cityNumber
    }
}
// 省份类
class Province{
    var citys = Dictionary<Int,City>()
    var proviceName:String!
    init(proviceName:String) {
        self.proviceName = proviceName
    }
    subscript(cityId:Int)->City{
        get{
            return citys[cityId]!
        }
        set{
            citys[cityId] = newValue
        }
    }
}
// 国家类
class Country{
    var provinces = Dictionary<Int,Province>()
    subscript(provinceId:Int,cityId:Int)->City{
        get{
            assert(provinceId>maxNumberOfProvice, "省份最多\(maxNumberOfProvice)个")
            assert(cityId>maxNumberOfCity, "每个省份城市最多\(maxNumberOfCity)个")
            var province = provinces[provinceId]!
            var city = province[cityId]
            return city
        }
        set{
            var province:Province = provinces[provinceId]!
            province[cityId] = newValue

        }
    }
    subscript(provinceId:Int)->Province{
        get{
            assert(provinceId>maxNumberOfProvice, "省份最多\(maxNumberOfProvice)个")
            return provinces[provinceId]!
        }
        set{
            provinces[provinceId] = newValue
        }
    }

}

var country = Country()
for provinceId in 1...maxNumberOfProvice {
    var provice = Province(proviceName: "省份:\(provinceId)")
    for cityId in 1...maxNumberOfCity {
        var city = City(cityName: "省份:\(provinceId) - 城市:\(cityId)", cityNumber: cityId)
        provice[cityId] = city
    }
    country[provinceId] = provice
}

print(country[3,306].cityName)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值