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
// 正常打印销毁
相关推荐
胡萝卜术1 小时前
从内存视角重新认识 JavaScript 数据类型:一份深度学习笔记
前端·javascript·面试
IVEN_1 小时前
记一次诡异的前端白屏故障:Nginx Proxy Cache 内存缓存"幽灵"事件
前端·nginx
如果超人不会飞1 小时前
TinyRobot SuggestionPills紧凑的建议按钮组组件
前端·vue.js
如果超人不会飞1 小时前
TinyRobot Container构建优雅的AI对话容器
前端·vue.js
幸运小圣1 小时前
全面解析 Web 核心性能指标:LCP、INP、CLS 是什么、怎么用、怎么看
前端
如果超人不会飞1 小时前
TinyRobot SuggestionPopover智能建议弹出框组件
前端·vue.js
LiuJun2Son2 小时前
Angular 快速入门:从零搭建你的第一个应用
前端·javascript·angular.js
小徐_23332 小时前
Wot UI 2.1.0 发布:ConfigProvider 全局配置能力升级
前端·uni-app
方白羽2 小时前
Vibe Coding 四个核心阶段
android·前端·app