您的当前位置:首页正文

【swift笔记】 之 class(类)和struct(结构体

2024-12-19 来源:二三四教育网

Swift中类(Class)和 结构体(Struct)

分析

共同点:

  • 定义属性用于存储值
  • 定义方法用于提供功能
  • 定义下标操作使得可以通过下标语法来访问实例所包含的值
  • 定义构造器用于生成初始化值
  • 通过扩展以增加默认实现的功能
  • 实现协议以提供某种标准功能

与结构体相比,类还有如下的附加功能:

  • 继承允许一个类继承另一个类的特征
  • 类型转换允许在运行时检查和解释一个类实例的类型
  • 析构器允许一个类实例释放任何其所被分配的资源
  • 引用计数允许对一个类的多次引用(对象引用)结构体总是通过被复制的方式在代码中传递,不使用引用计数。

逐一对比

定义

//: ### 定义
class StudentClass{ }
struct StudebtStruct{ }

定义存储属性

//: > 类中定义的存储属性,如果不是可选类型,需要进行初始化;结构体则默认带有初始化方法
class StudentC01{
    var name: String!
}
struct StudebtS01{
    var name: String!
}

定义属性函数function

//: ### 定义属性函数function
//: > 类中可以使用 static 和 class两种修饰符;但是结构体中只能使用static修饰
class StudentC02{
    static var des:String = "学生的类"
    var name:String!
    @objc class func objc_describe()->String{
        return des
    }
    class func class_describe()->String{
        return des
    }
    static func static_describe()->String{
        return des
    }
}
struct StudentS02{
    static var des:String = "学生的结构体"
    var name:String!
    static func describe()->String{
        return "这是一个定义学生的类"
    }
}

扩展下标

//: ### 扩展下标
//: > *subscript*
class StudentC003{
    var names:[String] = ["1","2","3","4","5"]
    subscript (index:Int)->String?{
        get{
            if names.count <= index{
                return nil
            }
            return names[index]
        }
    }
}
struct StudentS003{
    var names:[String] = ["1","2","3","4","5"]
    subscript (index:Int)->String?{
        get{
            if names.count <= index{
                return nil
            }
            return names[index]
        }
    }
}
let sc003 = StudentC003()
sc003[1]// 2
let ss003 = StudentS003()
ss003[1]// 2

初始化

//: ### 初始化
//: > 结构体自带初始化方法(可以不写初始化方法);
//: > 类必须手写init方法,否则报错;
class StudentC004{
    var name:String
    init(name:String) {
        self.name = name
    }
}
struct StudentS004 {
    var name:String
    
}
let studentc004 = StudentC004(name: "行走在北方")
let students004 = StudentS004(name: "行走在北方")

扩展功能 Extention

//: ### 扩展功能 Extention
extension StudentC004{
    func discribe() -> String {
        return "student class:"+self.name
    }
}
extension StudentS004{
    func discribe() -> String {
        return "student struct:" + self.name
    }
}

实现协议 protocol

//: ### 实现协议 protocol
//: * 定义协议
protocol Capacity {
    func draw()//协议方法
}
//: * 实现协议方法
class StudentC05:Capacity{
    internal func draw() {
        
    }
    var name:String
    init(name:String) {
        self.name = name
    }
}
struct StudentS05:Capacity{
    internal func draw() {
        
    }
    var name:String
}

mutating 关键字的使用

科普下:

  • 枚举和结构体都是值类型,Swift默认值类型的对象方法不能修改属性值,但是如果一定要修改 那就在函数前面添加mutating关键字

  • 计算属性setter方法中不需要更改属性值的时候,不需要添加mutating关键字;

  • 计算属性setter方法中更改属性值的时候,必须要添加mutating关键字

protocol Action{
    var myY:Int{
        mutating get
    }
}
struct Point {
    var x:Int
    var y:Int
    mutating func modifyX(x: Int){
        self.x = x
    }
    var myY:Int{
        mutating get {//getter方法前面添加mutating关键字
            self.y = self.y*2
            return y
        }
    }
}
class ActionClass {
    var name:String?
    init(name:String) {
        self.name = name
    }
    var myName:String? {
        get {// class 是对象类型 可以直接修改
            self.name = "666 -> :" + self.name!
            return self.name
        }
    }
    
}
let actionclass = ActionClass(name: "NB")

判断两个对象地址是否相同(验证 引用类型 和 值类型)

//: ### 判断两个对象地址是否相同
//: > 类是引用类型;结构体是值类型;结构体不能通过=== 、!==类判断比较
//: >
class StudentC07{
    var name: String
    init(name:String) {
        self.name = name
    }
}

let studentc071 = StudentC07(name: "原始名字")
var studentc072 = studentc071
studentc071.name = "新名字"
print("student071:\(studentc071.name)\nstudent072:\(studentc072.name)")
if studentc071 === studentc072 {
    print("类是引用类型,最终指向同一块内存")
}
struct StudentS07{
    var name: String
    init(name:String) {
        self.name = name
    }
}
let students071 = StudentS07(name: "结构体:原始名字")
var students072 = students071
students072.name = "结构体:新名字"
print("students071:\(students071.name)\nstudents072\(students072.name)")

deinit 释放资源

//: ### deinit 释放资源
//: > 类有deinit方法;结构体中没有deinit方法。
class StudentC08{
    var name: String
    init(name:String) {
        self.name = name
    }
    deinit {
        //这里释放资源
    }
}

lazy:延迟属性(懒加载)

class 有延迟属性;struct没有延迟属性

//: > 延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用 lazy 来标示一个延迟存储属性
class Importor{
    var fileName = "data.txt"
}
class DataManager{
    lazy var importor = Importor()
    var Data = [String]()
}

继承

//: ### 继承
//: > 类能继承;结构体不能继承。
class Person{
    var name:String
    init(name:String) {
        self.name = name
    }
}
class Student06: Person {
    var score : Float
    init(name: String, score: Float){
        self.score = score//先给父类中没有的属性赋值,再调用父类init方法
        super.init(name: name)
    }
}   
  • 继承之后 可重写父类方法/属性

    1. 重写计算属性:只能增加功能不能减少功能——>父类中有setter getter,那么子类重写计算属性 setter getter都必须要有。父类中只有setter 子类中可以在重写setter的同时增加getter

    2. final 关键字可以让属性不被重写 或者 继承

//: * 重写计算属性
//: * 重写对象方法
//: * 重写类方法
//: * 重写初始化方法
//: * 重写存储属性

//: _父类_
class Person{
    //存储属性
    var name:String = "person"
    //计算属性
    var rename:String{
        return self.name
    }
    //初始化方法
    init(_ name:String) {
        self.name = name
    }
    //对象方法
    func describe() -> String {
        return self.name
    }
    //类方法
    class func describeClass()->String{
        return "这是一个描述人的类"
    }
}
//: _子类_
class Man: Person {
    //重写存储属性
    override var name: String{
        didSet{
            print("man 对象中 name 的原始值:\(self.name)")
            self.name = "man:"+self.name
        }
    }
    var score : Double
    //重写setter getter
    override var rename: String{
        set{
            self.name = "man:"+newValue
        }
        get{
            return "_"+self.name
        }
    }
    //重写初始化方法
    override init(_ name: String) {
        self.score = 0.0
        super.init(name)
    }
    //重写对象方法
    override func describe() -> String {
        return self.name + "_score:\(self.score)"
    }
    // 重写类方法
    override class func describeClass() -> String {
        return "我是描述男人的类"
    }
}
var man00 = Man("kael")
print(man00.name)

class 的类型检测

  1. 首先在自己的初始化方法中先给自己的属性初始化
  2. 然后调用父类的初始化
  3. 最后修改父类的属性
//: ### 类型检测  is  as?
var person01 = Person("person01")
var man01 = Man("man01")

if person01 is Person {
    print("person01:我是Person")
}else{
    print("person01:我不是Person")
}
if person01 is Man {
    print("person01:我是Man")
}else{
    print("person01:我不是Man")
}
if man01 is Person {
    print("man01:我是Person")
}else{
    print("man01:我不是Person")
}
if man01 is Man {
    print("man01:我是Man")
}else{
    print("man01:我不是Man")
}

if let p = person01 as? Person {
    print("person01 是 Person")
}
if let p = person01 as? Man{
    print("person01 是Man")
}else{
    print("person01 不是Man")
}
if let p = man01 as? Person {
    print("man01 是 Person")
}
if let p = man01 as? Man{
    print("man01 是Man")
}else{
    print("man01 不是Man")
}


显示全文