Swift类与结构体_8

2017-11-22  本文已影响2人  edison0428

类和结构体是人们构建代码所用的一种通用切灵活的构造体,我们可以使用完全相同的语法规则来为类和结构体定义属性(常量,变量)和添加方法,从而拓展类和结构体的功能
与其他编程语言所不同的是,swift并不要求你为自定义类和结构体去创建独立的接口和实现文件,你所要做的是在一个单一文件中定义一个类或者结构体,系统将自动生成面向其他代码的外部接口

通常一个类的实例被称之为对象,然而在swift中,类和结构体的关系要比其他语言中更加密切

类和结构体对比

swift中类和结构体有很多共同点

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

结构体总是通过被复制的方法在代码中传递,不使用引用计数

定义语法
//类的定义
class EYTestClass: NSObject {
    
}
//结构体的定义
struct EYTestStruct {
    
}

在每次定义一个新类的或者结构体的时候,实际上定义一个新的swift类型,因此请使用UpperCamelCase这种方式来命名,请使用lowerCamelCase这种方式为属性和方法命名,以便于和类型名区别

以下是定义结构体和定义类的实例

//结构体的定义
struct EYTestStruct {
    
    var width = 100
    var height = 100
    
    
}
//类的定义
class EYTestClass: NSObject {
    
    var isBig = true
    var len = 20
    var name :String?
    var testStruct = EYTestStruct()
    
    
    func getLen() -> Int {
        
        return len
    }
    
    
}

类和结构体实例

生成结构体和类实例的语法非常相似

 var testClass = EYTestClass()
        
 var testStruct = EYTestStruct()

结构体和类都是使用构造器语法来生成新的实例,构造器语法的最简单形式是在结构体或者类的类型名称后跟随一对空括号,通过这种方式所创建的类或者接头体实例,其属性会被初始化默认值

属性访问

通过使用点语法,你可以访问实例的属性。其语法规则是,实例名后面紧跟属性名,两者通过点号(.)连接

var testStruct = EYTestStruct()
testStruct.height = 20
testStruct.height = 10
        
let infoTest = EYInfo()
infoTest.age = 10
infoTest.name = "Edison"
infoTest.isMar = false
print("\(infoTest.age) \(infoTest.name) \(infoTest.isMar)")

注意,与oc语言不同的是,swift允许直接设置结构体属性的子属性,就是直接设置了testStruct属性的width这个子属性,以上操作并不需要重新为整个height属性设置新值,对比oc中的cgrect cgpoint就知道了

结构体类型的成员逐一构造器

所有结构体都有一个自动生成的成员注意构造器,用于初始化新结构体实例中成员的属性,新实例中各个属性的初始值可以通过属性的名称传递到成员的逐一构造器中

let testStruct2 = EYTestStruct(width:10,height:20)
print("=\(testStruct2)")
//reslut :=EYTestStruct(width: 10, height: 20)

与结构体不同,类实例没有默认的成员逐一构造器

结构体和枚举是值类型

值类型被赋予一个变量,常量或者被传递给一个函数的时候,其值会被拷贝
在之前的章节中,我们已经大量使用值类型,实际上,在swift中,所有的基本类型:整数(Integer),浮点数(Float),布尔值(Boolean),字符串(String),数组(array),字典(Dictionary),都是值类型,并且在底层都是以结构体的形式所实现
在 Swift 中,所有的结构体和枚举类型都是值类型。这意味着它们的实例,以及实例中所包含的任何值类型属性,在代码中传递的时候都会被复制

 let testStruct2 = EYTestStruct(width:10,height:20)
 print("=\(testStruct2)")
 //reslut :=EYTestStruct(width: 10, height: 20)
 var testStruct3 = testStruct2
 testStruct3.width =  20
 testStruct3.height = 40
 print("=\(testStruct3)")
 //result :=EYTestStruct(width: 20, height: 40)
类是引用类型

与值类型不同,引用类型在被赋予到一个变量、常量或者被传递到一个函数时,其值不会被拷贝。因此,引用的是已存在的实例本身而不是其拷贝

        let infoTest = EYInfo()
        infoTest.age = 10
        infoTest.name = "Edison"
        infoTest.isMar = false
        print("\(infoTest.age) \(infoTest.name) \(infoTest.isMar)")
        
        let infoTest2 = infoTest
        
        infoTest2.age = 20
        infoTest2.name = "Edison2"
        infoTest2.isMar = true
        print("==\(infoTest.age) \(infoTest.name) \(infoTest.isMar)")
        print("==\(infoTest2.age) \(infoTest2.name) \(infoTest2.isMar)")
        
        /*
         result:
         ==20 Edison2 true
         ==20 Edison2 true
         */

如以修改infoTest2后,infoTest的值也改变了

恒等运算

因为类是引用类型,有可能有多个常量和变量在幕后同时引用同一个类实例。(对于结构体和枚举来说,这并不成立。因为它们作为值类型,在被赋予到常量、变量或者传递到函数时,其值总是会被拷贝。)

如果能够判定两个常量或者变量是否引用同一个类实例将会很有帮助。为了达到这个目的,Swift 内建了两个恒等运算符

        if infoTest === infoTest2{
            
            print("引用同一个实例")
        }else{
            print("不引用同一个实例")
        }
        
        let infoTest4 = EYInfo()
        infoTest.age = 10
        infoTest.name = "Edison"
        infoTest.isMar = false
        print("\(infoTest.age) \(infoTest.name) \(infoTest.isMar)")
        
        
        if infoTest === infoTest4{
            
            print("引用同一个实例")
        }else{
            print("不引用同一个实例")
        }

指针

coc中,都是使用指针来引用内存中的地址,一个引用某个引用类型实例的swift常量或者变量,与C语言中的指针类似,但是并不是直接指向某个内存地址,也不要求使用*来标明你在创建一个引用个,swift中这些引用与其他的常量或变量的定义方式相同

类和结构体的选择

在你的代码中,你可以使用类和结构体来定义你的自定义数据类型。

然而,结构体实例总是通过值传递,类实例总是通过引用传递。这意味两者适用不同的任务。当你在考虑一个工程项目的数据结构和功能的时候,你需要决定每个数据结构是定义成类还是结构体。

按照通用的准则,当符合一条或多条以下条件时,请考虑构建结构体

上一篇下一篇

猜你喜欢

热点阅读