进口彩妆做的好的网站,品牌网站设计服务,商标注册查询怎么查,网站开发的数据库设计实体是什么类和结构体 一、结构体和类对比1、类型定义的语法2、结构体和类的实例3、属性访问4、结构体类型的成员逐一构造器 二、结构体和枚举是值类型三、类是引用类型1、恒等运算符2、指针 结构体和类作为一种通用而又灵活的结构#xff0c;成为了人们构建代码的基础。你可以使用定义常… 类和结构体 一、结构体和类对比1、类型定义的语法2、结构体和类的实例3、属性访问4、结构体类型的成员逐一构造器 二、结构体和枚举是值类型三、类是引用类型1、恒等运算符2、指针 结构体和类作为一种通用而又灵活的结构成为了人们构建代码的基础。你可以使用定义常量、变量和函数的语法为你的结构体和类定义属性、添加方法。 与其他编程语言所不同的是Swift 并不要求你为自定义的结构体和类的接口与实现代码分别创建文件。你只需在单一的文件中定义一个结构体或者类系统将会自动生成面向其它代码的外部接口。 注意 通常一个类的实例被称为对象。然而相比其他语言Swift 中结构体和类的功能更加相近本章中所讨论的大部分功能都可以用在结构体或者类上。因此这里会使用实例这个更通用的术语。 一、结构体和类对比
Swift 中结构体和类有很多共同点。两者都可以
定义属性用于存储值定义方法用于提供功能定义下标操作用于通过下标语法访问它们的值定义构造器用于设置初始值通过扩展以增加默认实现之外的功能遵循协议以提供某种标准功能
与结构体相比类还有如下的附加功能
继承允许一个类继承另一个类的特征类型转换允许在运行时检查和解释一个类实例的类型析构器允许一个类实例释放任何其所被分配的资源引用计数允许对一个类的多次引用
类支持的附加功能是以增加复杂性为代价的。作为一般准则优先使用结构体因为他们更容易理解仅在适当或必要时才使用类。实际上这意味着你的大多数自定义数据类型都会是结构体和枚举。
1、类型定义的语法
结构体和类有着相似的定义方式。你通过 struct 关键字引入结构体通过 class 关键字引入类并将它们的具体定义放在一对大括号中
struct SomeStructure {// 在这里定义结构体
}
class SomeClass {// 在这里定义类
}注意 每当你定义一个新的结构体或者类时你都是定义了一个新的 Swift 类型。请使用 UpperCamelCase这种方式来命名类型如这里的 SomeClass 和 SomeStructure 以便符合标准 Swift 类型的大写命名风格如 String Int 和 Bool。请使用 lowerCamelCase 这种方式来命名属性和方法如 frameRate 和 incrementCount以便和类型名区分。 以下是定义结构体和定义类的示例
struct Resolution {var width 0var height 0
}
class VideoMode {var resolution Resolution()var interlaced falsevar frameRate 0.0var name: String?
}在上面的示例中定义了一个名为 Resolution 的结构体用来描述基于像素的分辨率。这个结构体包含了名为 width 和 height 的两个存储属性。存储属性是与结构体或者类绑定的并存储在其中的常量或变量。当这两个属性被初始化为整数 0 的时候它们会被推断为 Int 类型。
在上面的示例还定义了一个名为 VideoMode 的类用来描述视频显示器的某个特定视频模式。这个类包含了四个可变的存储属性。第一个 resolution被初始化为一个新的 Resolution 结构体的实例属性类型被推断为 Resolution。新 VideoMode 实例同时还会初始化其它三个属性它们分别是初始值为 false 的 interlaced意为“非隔行视频”初始值为 0.0 的 frameRate以及值为可选 String 的 name。因为 name 是一个可选类型它会被自动赋予一个默认值 nil意为“没有 name 值”。
2、结构体和类的实例
Resolution 结构体和 VideoMode 类的定义仅描述了什么是 Resolution 和 VideoMode。它们并没有描述一个特定的分辨率resolution或者视频模式video mode。为此你需要创建结构体或者类的一个实例。
创建结构体和类实例的语法非常相似
let someResolution Resolution()
let someVideoMode VideoMode()结构体和类都使用构造器语法来创建新的实例。构造器语法的最简单形式是在结构体或者类的类型名称后跟随一对空括号如 Resolution() 或 VideoMode()。通过这种方式所创建的类或者结构体实例其属性均会被初始化为默认值。构造过程 章节会对类和结构体的初始化进行更详细的讨论。
3、属性访问
你可以通过使用点语法访问实例的属性。其语法规则是实例名后面紧跟属性名两者以点号.分隔不带空格
print(The width of someResolution is \(someResolution.width))
// 打印 The width of someResolution is 0在上面的例子中someResolution.width 引用 someResolution 的 width 属性返回 width 的初始值 0。
你也可以访问子属性如 VideoMode 中 resolution 属性的 width 属性
print(The width of someVideoMode is \(someVideoMode.resolution.width))
// 打印 The width of someVideoMode is 0你也可以使用点语法为可变属性赋值
someVideoMode.resolution.width 1280
print(The width of someVideoMode is now \(someVideoMode.resolution.width))
// 打印 The width of someVideoMode is now 12804、结构体类型的成员逐一构造器
所有结构体都有一个自动生成的成员逐一构造器用于初始化新结构体实例中成员的属性。新实例中各个属性的初始值可以通过属性的名称传递到成员逐一构造器之中
let vga Resolution(width: 640, height: 480)注意 与结构体不同类实例没有默认的成员逐一构造器。 二、结构体和枚举是值类型
值类型是这样一种类型当它被赋值给一个变量、常量或者被传递给一个函数的时候其值会被拷贝。
在之前的章节中你已经大量使用了值类型。实际上Swift 中所有的基本类型整数integer、浮点数floating-point number、布尔值boolean、字符串string)、数组array和字典dictionary都是值类型其底层也是使用结构体实现的。
Swift 中所有的结构体和枚举类型都是值类型。这意味着它们的实例以及实例中所包含的任何值类型的属性在代码中传递的时候都会被复制。 注意 标准库定义的集合例如数组字典和字符串都对复制进行了优化以降低性能成本。新集合不会立即复制而是跟原集合共享同一份内存共享同样的元素。在集合的某个副本要被修改前才会复制它的元素。而你在代码中看起来就像是立即发生了复制。 请看下面这个示例其使用了上一个示例中的 Resolution 结构体
let hd Resolution(width: 1920, height: 1080)
var cinema hd在以上示例中声明了一个名为 hd 的常量其值为一个初始化为全高清视频分辨率1920 像素宽1080 像素高的 Resolution 实例。
然后示例中又声明了一个名为 cinema 的变量并将 hd 赋值给它。因为 Resolution 是一个结构体所以会先创建一个现有实例的副本然后将副本赋值给 cinema 。尽管 hd 和 cinema 有着相同的宽width和高height但是在幕后它们是两个完全不同的实例。
下面为了符合数码影院放映的需求2048 像素宽1080 像素高cinema 的 width 属性被修改为稍微宽一点的 2K 标准
cinema.width 2048查看 cinema 的 width 属性它的值确实改为了 2048
print(cinema is now \(cinema.width) pixels wide)
// 打印 cinema is now 2048 pixels wide然而初始的 hd 实例中 width 属性还是 1920
print(hd is still \(hd.width) pixels wide)
// 打印 hd is still 1920 pixels wide将 hd 赋值给 cinema 时hd 中所存储的值会拷贝到新的 cinema 实例中。结果就是两个完全独立的实例包含了相同的数值。由于两者相互独立因此将 cinema 的 width 修改为 2048 并不会影响 hd 中的 width 的值如下图所示 枚举也遵循相同的行为准则
enum CompassPoint {case north, south, east, westmutating func turnNorth() {self .north}
}
var currentDirection CompassPoint.west
let rememberedDirection currentDirection
currentDirection.turnNorth()
print(The current direction is \(currentDirection))
print(The remembered direction is \(rememberedDirection))
// 打印 The current direction is north
// 打印 The remembered direction is west当 rememberedDirection 被赋予了 currentDirection 的值实际上它被赋予的是值的一个拷贝。赋值过程结束后再修改 currentDirection 的值并不影响 rememberedDirection 所储存的原始值的拷贝。
三、类是引用类型
与值类型不同引用类型在被赋予到一个变量、常量或者被传递到一个函数时其值不会被拷贝。因此使用的是已存在实例的引用而不是其拷贝。
请看下面这个示例其使用了之前定义的 VideoMode 类
let tenEighty VideoMode()
tenEighty.resolution hd
tenEighty.interlaced true
tenEighty.name 1080i
tenEighty.frameRate 25.0以上示例中声明了一个名为 tenEighty 的常量并让其引用一个 VideoMode 类的新实例。它的视频模式video mode被赋值为之前创建的 HD 分辨率1920*1080的一个拷贝。然后将它设置为隔行视频名字设为 “1080i”并将帧率设置为 25.0 帧每秒。
接下来将 tenEighty 赋值给一个名为 alsoTenEighty 的新常量并修改 alsoTenEighty 的帧率
let alsoTenEighty tenEighty
alsoTenEighty.frameRate 30.0因为类是引用类型所以 tenEight 和 alsoTenEight 实际上引用的是同一个 VideoMode 实例。换句话说它们是同一个实例的两种叫法如下图所示 通过查看 tenEighty 的 frameRate 属性可以看到它正确地显示了底层的 VideoMode 实例的新帧率 30.0
print(The frameRate property of tenEighty is now \(tenEighty.frameRate))
// 打印 The frameRate property of theEighty is now 30.0这个例子也显示了为何引用类型更加难以理解。如果 tenEighty 和 alsoTenEighty 在你代码中的位置相距很远那么就很难找到所有修改视频模式的地方。无论在哪使用 tenEighty你都要考虑使用 alsoTenEighty 的代码反之亦然。相反值类型就更容易理解了因为你的源码中与同一个值交互的代码都很近。
需要注意的是 tenEighty 和 alsoTenEighty 被声明为常量而不是变量。然而你依然可以改变 tenEighty.frameRate 和 alsoTenEighty.frameRate这是因为 tenEighty 和 alsoTenEighty 这两个常量的值并未改变。它们并不“存储”这个 VideoMode 实例而仅仅是对 VideoMode 实例的引用。所以改变的是底层 VideoMode 实例的 frameRate 属性而不是指向 VideoMode 的常量引用的值。
1、恒等运算符
因为类是引用类型所以多个常量和变量可能在幕后同时引用同一个类实例。对于结构体和枚举来说这并不成立。因为它们作为值类型在被赋予到常量、变量或者传递到函数时其值总是会被拷贝。
判定两个常量或者变量是否引用同一个类实例有时很有用。为了达到这个目的Swift 提供了两个恒等运算符
相同不相同!
使用这两个运算符检测两个常量或者变量是否引用了同一个实例
if tenEighty alsoTenEighty {print(tenEighty and alsoTenEighty refer to the same VideoMode instance.)
}
// 打印 tenEighty and alsoTenEighty refer to the same VideoMode instance.请注意“相同”用三个等号表示与“等于”用两个等号表示的不同。“相同”表示两个类类型class type的常量或者变量引用同一个类实例。“等于”表示两个实例的值“相等”或“等价”判定时要遵照设计者定义的评判标准。
当在定义你的自定义结构体和类的时候你有义务来决定判定两个实例“相等”的标准
2、指针
如果你有 CC 或者 Objective-C 语言的经验那么你也许会知道这些语言使用指针来引用内存中的地址。Swift 中引用了某个引用类型实例的常量或变量与 C 语言中的指针类似不过它并不直接指向某个内存地址也不要求你使用星号*来表明你在创建一个引用。相反Swift 中引用的定义方式与其它的常量或变量的一样。