Swift 类,结构体,枚举使用总结

本文总结了Swift中类、结构体和枚举的相同点与不同点,强调了引用类型的特点,在赋值传递时实际是引用传递。建议在特定条件下优先使用结构体,如封装简单数据、不需要继承多态等。同时,探讨了`static`和`class`关键字以及它们与`protocol`的关系。
摘要由CSDN通过智能技术生成

类,结构体,枚举相同与不同

相同之处在于:

1:都可以通过定义不同的属性来保存自己的数据.
2:都可以通过定义方法来实现不同的功能.
3:都可以在定义下标方法后,通过下标方法的语法来获取和修改自己保存的值.
4:都可以定义构造器来设置不同属性的初始值.
5:都可以使用extention关键字来扩充其功能.
6:都可以遵守协议来通过特定种类的功能.

不同之处:

1:类支持继承.
2:类支持类型转换,允许你在运行时检测和解释类实例的类型,也就是多态.
3:类支持析构,可以自动回收类实例说掌控的资源.
4:类实例支持自动引用计数(ARC).
5:类属于引用类型,而枚举和结构体属于值类型.枚举,结构体因为是值类型,所以没有ARC.

值类型的特点如下:

1:在赋值给常量或变量的过程中,赋给变量或常量的是该类型的值的一个副本.
2:在作为参数传递给函数时,传递的是该类型的副本.
3:值类型之特权--变质方法.(注意:在 swift 中除了类都是值类型.)在实例方法中有一个特殊的方法,称之为变质方法.是因为它可以直接修改当前实例,而不是在当前实例的基础上修改其中的某些属性,该方法是值类型的专属方法,即只能够用在结构体和枚举类型上.

下面看一个有关于变质方法的例子:

struct Warcraft{

    var sense: String
    var money: Int
    
    mutating func jumpToSense(sense: String){
    
        //直接生成一个新的Warcraft实例,而不是单纯地修改sense和money.
        self = Warcraft(sense: sense, money: 100)
    }
}

func testOne(){
    
        //新的游戏,新的场景游戏币为200
        var myWarcraft = Warcraft(sense: "无间地狱", money: 200)
        
        //疯狂练级,赚了1000金币
        myWarcraft.money = 1000
        
        print("当前场景:\(myWarcraft.sense) 当前金币:\(myWarcraft.money)")
        //当前场景:无间地狱 当前金币:1000
        
        //水平太差,死掉,恢复到魔域之火场景,金币丢失.这里直接重置当前实例!
        myWarcraft.jumpToSense("魔域之火")
        print("当前场景:\(myWarcraft.sense) 当前金币:\(myWarcraft.money)")
        //当前场景:魔域之火 当前金币:100
        
    } 

引用类型的特点

在赋值做作为参数传递给函数时,传递的不是一个值副本,而是对同一现有实例的一个引用!

//引用类型代码:
class SomeClass{

    var name: String
    init(name: String){
    
        self.name = name
    }
}

//值类型代码:
struct SomeSturct{

    var name: String
    init(name: String){
    
        self.name = name
    }
}

func testTwo(){
    
        var aClass = SomeClass(name: "jack")
        var bClass = aClass  //aClass和bClass是对同一实例的引用.
        bClass.name = "jenny"
        
        //因为类是引用类型,所以结果必然一样.
        print("aClass.name=\(aClass.name) bClass.name=\(bClass.name)")
        //aClass.name=jenny bClass.name=jenny
        
        var aStruct = SomeSturct(name: "lisa")
        var bStruct = aStruct
        bStruct.name = "judy"
        
        print("aStruct.name=\(aStruct.name) bStruct.name=\(bStruct.name)")
        //aStruct.name=lisa bStruct.name=judy
        
        if aClass === bClass{
        
            print("aClass和bClass引用了同一类实例")
        }
        
        if !(aClass !== bClass){
          
            print("aClass和bClass引用了同一类实例")
        }
        
        //以上两个判断语句都输出:aClass和bClass引用了同一类实例
    }


有上面的例子我们就能够明白:

    1:引用类型在赋值和作为参数传递的过程中,传递的是对该类实例的一个引用.我们一旦通过引用修改了该类实例中属性的值,将会导致其它所有引用该类实例的常量或者变量中的属性发生改变.
    2:值类型则不会,因为值类型传递的是该实例的一个副本,内存中两个实例拥有不同的内存地址,所以当我们修改了bStruct中属性的 name的值后,并不会同时修改aStruct中属性name的值.
    这里注意,如果不确定常量或者变量是否引用了相同的类实例,可以通过===和!==来判断两个不同的常量或者变量是否引用了同一个类实例.

建议:在绝大多数情况下我们应该使用类来封装自定义数据类型,只有在满足如下条件下,应优先考虑结构体.

    1:只是用于封装简单的数据时,如位置信息.
    2:该封装数据中的值在赋值或者传参时,应该是传复制的值而不是传引用的值,如 swift 中基本的数据类型Int,Double,String等.
    3:该类型需要独立存在,不需要任何继承关系,多态特性时选用结构体.
    4:记住:类是属性和方法的集合,而结构体和枚举是关联数据的集合.

    

static 和 class

Swift 中表示 “类型范围作用域” 这一概念有两个不同的关键字,它们分别是static和class。在非clasa的类型上下文中,我们统一使用static来描述类型作用域。这包括在enum和struct中表述类型方法和类型属性时。在这两个值类型中,我们可以在类型范围内声明并使用存储属性,计算属性和方法.static适用的场景有这些:

struct Point {
    let x: Double
    let y: Double
    
    //存储属性
    static let zero = Point(x: 0, y: 0)
    
    //计算属性
    static var ones: [Point] {
        return [Point(x:1, y:1)]
    }
    
    //类方法
    static func add(_ p1: Point, _ p2: Point) -> Point {
        return Point(x: p1.x + p2.x, y: p1.y + p2.y)
    }
}
enum的情况与这里类似。对于class关键字相比起来就明白许多,是专門用在class 类型的上下文中的,可以用来修饰类方法以及类的计算属性。但是有一个例外,class中现在是不能出现class的存储属性的,我们如果写类似这样的代码的话:

class Person {
    class var age: Int?
}
但是我们可以使用static

class Person {
    static var age: Int?
}

static与protocol


在Swift中class,enum,struct都是可以实现某个protocol的。那么如果我们想在protocol里定义一个类型域上的方法或者计算属性的话,我们可以使用static进行定义。在使用的时候,enum或struct仍然使用static,而在class里我们既可以使用class关键字,也可以用static,它们的结果是相同的:


protocol MyProtocol {
    static func foo() -> String
}

struct MyStruct: MyProtocol {
    static func foo() -> String {
        return "MyStruct"
    }
}

enum MyEnum: MyProtocol {
    static func foo() -> String {
        return "MyEnum"
    }
}

class MyClass: MyProtocol {
    class func foo() -> String {
        return "MyClass.foo()"
    }
    
    static func bar() -> String {
     return "MyClass.bar()"
    }
}







    
   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值