swift (三) 枚举 结构体 类

枚举

csharp 复制代码
enum Sex {
    case woman
    case man
}

var a = Sex.woman
// 当a的类型确定好之后,可以采用简写
a = .man

枚举的递归,枚举的默认值等用的很少。

结构体和类

结构体可以不给默认值,类如果没有默认值,必须添加初始化方法

ini 复制代码
class Student{
    var name:String = ""
    var age:Int = 0
}


class Student1{
    var name:String = ""
    var age:Int
    init(){
        // 只要有变量没有默认值,就必须提供初始化方法
        age = 20
    }
}
var s = Student()
var s1 = Student1()

// 结构体是值类型,类是引用类型
// 值类型的优点是速度快,分配在栈空间
var pp = Person()
pp.age = 20
var pp1 = pp
pp.age = 200
print(pp1.age) //还是默认值20

var ss = Student()
ss.age = 20
var ss1 = ss
ss.age = 200
print(ss1.age) // 200,已经被修改了

// 恒等运算符 === !==
// 只有2个变量或者常量指向同一个内存空间才算

if ss === ss1 {
    print("===")
}

存储属性

ini 复制代码
// 存储属性
struct Student{
    var name:String
    var age:Int
}
class Student1{
    var name:String = ""
    var age:Int = 0
}
let s = Student(name: "", age: 20)
//s.age = 100 语法错误

// 类可以被修改
let s1 = Student1()
s1.age = 200

延迟存储属性

swift 复制代码
struct Person{
    lazy var name:String = {
        print("person name 初始化")
        return  "杜甫"
    }()
    var age:Int
}

class Person1 {
    lazy var name:String = {
        print("person1 name 初始化")
        return  "杜甫"
    }()
    var age:Int
    init(){
        age = 10
    }
}

var p = Person(age: 20)
print(p.age)
print(p.name) // 使用的时候才初始化

var p1 = Person1()
print(p1.age)
print(p1.name) // 使用的时候才初始化

计算属性

scss 复制代码
// 计算属性
struct Squre{
    var width:Double = 0
    var area:Double {
        get{
            return width * width
        }
        set(v){
            width = sqrt(v)
        }
    }
}

class Squre1{
    var width:Double = 0
    var area:Double {
        get{
            // 也可以直接省略return
            return width * width
        }
//        set(v){
//            width = sqrt(v)
//        }
        set{
            // 也可以用newValue
            width = sqrt(newValue)
        }
    }
    // 只读属性
    var perimeter:Double{
        width * 4
    }
}
var s = Squre()
s.area = 100
print(s.width)
s.width = 200
print(s.area)

var s1 = Squre1()
s1.area = 100
print(s1.width)
s1.width = 200
print(s1.area)
print(s1.perimeter)

属性观察器

作用域

  • 自定义的存储属性
  • 继承的存储属性和计算属性
swift 复制代码
class Student{
    var age:Int = 0 {
        willSet{
            print("will set ", newValue)
        }
        didSet{
            print("did set ", oldValue)
        }
    }
}
var s = Student()
s.age = 1000

方法

swift 复制代码
// 方法
struct Student{
    var name:String = ""
    var age:Int = 0

    //因为结构体是值类型, 默认是let不能修改self.因此必须使用mutaing声明
    mutating func changeAge(by age:Int){
        // 属性和形参同名称,需要用self区分
        self.age = age
    }
}
class Student1{
    var name:String = ""
    var age:Int = 0
    func changeAge(by age:Int){
        self.age = age
    }
}
var s = Student()
s.changeAge(by: 20)
print(s.age)

var s1 = Student1()
s1.changeAge(by: 20)
print(s1.age)

类方法

scss 复制代码
// 结构体方法和类方法
@MainActor
struct Student {
    static var count: Int = 1
    static func add() {
        count += 1
    }
    static func dec() {
        count -= 1
    }
    static func getTotal() -> Int {
        return count
    }
}

// static和class都是属于类方法
// static不能被子类重写
// class可以被子类重写
@MainActor
class Student1 {
    static var count: Int = 1
    static func add() {
        count += 1
    }
    class func dec() {
        count -= 1
    }
    class func getTotal() -> Int {
        return count
    }
}

Student.add()
print(Student.getTotal())
Student.add()
Student.add()
print(Student.getTotal())
Student.dec()
print(Student.getTotal())

Student1.add()
print(Student1.getTotal())
Student1.add()
Student1.add()
print(Student1.getTotal())

subscript 下标语法

final修饰的成员变量,方法,类方法都不能重写

swift 复制代码
struct Student {
    var age: Int = 0

    subscript(index: Int) -> Int {
        get {
            return age
        }
        set {
            age = newValue
        }
    }
}

class Student1 {
    var age: Int = 0

    subscript(index: Int) -> Int {
        get {
            return age
        }
        set {
            age = newValue
        }
    }
}

var s = Student()
s[0] = 100
print(s[2])

var s1 = Student1()
s1[100] = 20
print(s1[20])

// 这里只能通过下标获取数据,不能写入数据
struct Student2 {
    var age: Int = 0
    subscript(index: Int) -> Int {
        return age * index
    }
}

var s2 = Student2()
//s2[10] = 100 语法错误
print(s2[2000])

继承

swift 复制代码
class Animal{
    var age:Int = 0

    func eat(){
        print("animal eat")
    }
    func drink(){
        print("animal drink")
    }
    final func sleep(){
        print("animal sleep")
    }
}

class Person :Animal {
    var name:String = ""

    // 覆盖父类的方法需要写override
    override
    func drink() {
        // 也可以在子类通过super调用父类的方法
        super.drink()
        print("people drink water")

        super.sleep()
    }
}

var p = Person()
p.eat()
p.drink()

构造函数

  • init函数必须先调用父类的init函数
  • required init定义的函数,子类必须重写
swift 复制代码
// 构造函数
// 没有默认值,必须手动写一个init函数
struct Student{
    var name:String
    var age:Int
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

// Student1会自动生成一个init函数
struct Student1{
    var name:String = ""
    var age:Int = 0
}

var s = Student(name: "李白", age: 20)
var s1 = Student1()

// 因为有默认值,所以可以只给其中的部分属性赋值
var s2 = Student1(name:"hello")
print(s2.age)

便利构造器

  • 只能作用于class,不能作用在struct,enum
  • 必须调用其它init函数先进行初始化
  • 便利构造器只能调用当前类的构造函数和便利构造器,不能调用父类的便利构造器
  • 子类不能调用父类的便利构造器
swift 复制代码
class Person {
    var name: String
    var age: Int

    // 1. 指定构造器(主入口,初始化所有属性)
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

    // 2. 便利构造器:只传名字,年龄默认 0
    convenience init(name: String) {
        // 必须先调用本类指定构造器
        self.init(name: name, age: 0)
    }

    // 3. 便利构造器:无参,全部默认
    convenience init() {
        self.init(name: "未知")
    }
}

// 三种创建方式,全部合法
let p1 = Person(name: "小明", age: 20)
let p2 = Person(name: "小红")
let p3 = Person()

deinit

kotlin 复制代码
class Student{

    deinit{
        //1.用来释放资源
        //2. 验证Sdudent对象确实被释放了
    }
}

循环引用

swift 复制代码
// 这里就不会释放内存
class Student {
    var p: Person?
    deinit {
        print("sudent 释放了")
    }
}
class Person {
    var s: Student?
    deinit {
        print("person 释放了")
    }
}

var s: Student? = Student()
var p: Person? = Person()
s?.p = p
p?.s = s

s = nil
p = nil

// 改成weak
// 改成unowned但是不能访问,如果访问的时候空会报错
class Student {
    weak var p: Person?
    deinit {
        print("sudent 释放了")
    }
}
class Person {
    unowned var s: Student?
    deinit {
        print("person 释放了")
    }
}

var s: Student? = Student()
var p: Person? = Person()
s?.p = p
p?.s = s

s = nil
p = nil
swift 复制代码
// 闭包导致的循环引用
class Test {
    var closure: (() -> Void)?

    deinit {
        print("Test 销毁")
    }

    init() {
        // 闭包强捕获 self → 自循环引用
        closure = {
            print(self)
        }
    }
}

var t: Test? = Test()
t = nil
// deinit 不执行

// 闭包必须使用weak
class Test {
    var closure: (() -> Void)?

    deinit {
        print("Test 销毁")
    }

    init() {
        // 弱捕获 self
        closure = { [weak self] in
            guard let self = self else { return }
            print(self)
        }
    }
}

var t: Test? = Test()
t = nil
// 正常打印销毁
相关推荐
xixingzhe211 分钟前
本地桌面客户端入门开发
前端
不磕了还不行18 分钟前
用 Vue + Element UI 把元宝搜索的返回值做成“能点开检查的证据卡片”
前端·vue.js·ui
Csvn9 小时前
WASM
前端
修己xj11 小时前
我用 AI 给自己写了一个 Markdown 编辑器,然后把它开源了
前端
FRing0311 小时前
vue2干货总结2(v-bind、v-for、v-model、指令修饰符、v-bind操作class和style)
开发语言·前端·vue.js·vue2
幸运小猿11 小时前
模拟慢上传-处理超时重试image 丢失线上问题
前端·javascript·html
moshuying13 小时前
网购能买Token了!
前端
h_654321013 小时前
echarts实现柱状图加一条横线
前端·echarts
风骏时光牛马13 小时前
生成一个后端标题,只需要一个标题,不需要其他的任何文本。
前端
子非鱼@Itfuture13 小时前
关于前后端联调中登录状态/登录信息失效?
java·前端