Swift学习笔记(10):类和结构体
目录:
- 基本
- 属性
- 方法
- 下标
- 继承
基本
使用class和struct关键字定义类和结构体。
・类是引用类型,结构体和枚举是值类型
・值类型被赋予给一个变量、常量或被传递给一个函数时,已值拷贝方式传递
・可以使用 === 或 !== 判断两个类实例引用是否指向同一个类实例
class SomeClass {
// 在这里定义类
}
struct SomeStructure {
// 在这里定义结构体
}
使用类或结构体名称加 ()类创建类或结构体实例,使用 . 操作符引用属性名。
结构体都带有自动生成的成员逐一构造器,用于初始化新结构体实例中成员的属性。新实例中各个属性的初始值可以通过属性的名称传递到成员逐一构造器之中。类没有默认的成员逐一构造器。
let vga = Resolution(width:, height: )
属性
属性将值跟特定的类、结构或枚举关联。存储属性存储常量或变量作为实例的一部分,而计算属性计算一个值。计算属性可以用于类、结构体和枚举,存储属性只能用于类和结构体。还可以定义属性观察器来监控属性值的变化。
・存储属性
存储属性可以是变量存储属性(用关键字 var 定义),也可以是常量存储属性(用关键字 let 定义)。可以在定义存储属性的时候指定默认值,也可以在构造过程中设置或修改存储属性的值,甚至修改常量存储属性的值。
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: , length: )
由于结构体属于值类型,当值类型的实例被声明为常量的时候,它的所有属性也就成了常量。属于引用类型的类则不同,把一个引用类型的实例赋给一个常量后,仍然可以修改该实例的变量属性。
延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用 lazy 来标示一个延迟存 储属性。必须将延迟存储属性声明成变量(使用 var 关键字),因为属性的初始值可能在实例构造完成之后才会得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。
// DataImporter 是一个负责将外部文件中的数据导入的类。 这个类的初始化会消耗不少时间。
class DataImporter {
var fileName = "data.txt"
// 这里会提供数据导入功能
}
class DataManager {
lazy var importer = DataImporter() var data = [String]()
// 这里会提供数据管理功能
}
let manager = DataManager() manager.data.append("Some data") manager.data.append("Some more data")
// DataImporter 实例的 importer 属性还没有被创建
注意:如果一个被标记为 lazy 的属性在没有初始化时就同时被多个线程访问,则无法保证该属性只会被初始化一次。
・计算属性
计算属性不直接存储值,而是提供一个 getter 和一个可选的 setter,来间接获取和设置其他属性或变量的值。
struct Point {
var x = 0.0, y = 0.0
}
struct Size {
var width = 0.0, height = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / )
let centerY = origin.y + (size.height / )
return Point(x: centerX, y: centerY)
} // 如果计算属性的 setter 没有定义表示新值的参数名,
// 则可以使用默认名称 newValue
// set {
// origin.x = newValue.x - (size.width / 2)
// origin.y = newValue.y - (size.height / 2)
// }
set(newCenter) {
origin.x = newCenter.x - (size.width / )
origin.y = newCenter.y - (size.height / )
}
}
}
只有 getter 没有 setter 的计算属性就是只读计算属性。只读计算属性的声明可以去掉get关键字和花括号:
struct Cuboid {
var width = 0.0, height = 0.0, depth = 0.0
var volume: Double {
return width * height * depth
}
}
・属性观察器
属性观察器监控和响应属性值的变化,每次属性被设置值的时候都会调用属性观察器,即使新值和当前值相同的时候也不例外。可以为除了延迟存储属性之外的其他存储属性添加属性观察器,也可以通过重写属性的方式为继承的属性(包括存储属性和计算属性)添加属性观察器。
属性观察器包含:willSet 在新的值被设置之前调用; didSet 在新的值被设置之后立即调用。
class StepCounter {
var totalSteps: Int = {
willSet(newTotalSteps) {
print("About to set totalSteps to \(newTotalSteps)")
}
didSet {
// 默认值oldValue表示旧值的参数名
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
}
・类型属性
使用关键字 static 来定义类型属性。类型属性通过类型名加.操作符直接访问。在为类定义计算型类型属性时,可以改用关键字 class 来支持子类对父类的实现进行重写。
struct SomeStructure {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return
}
}
enum SomeEnumeration {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return
}
}
class SomeClass {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return
}
class var overrideableComputedTypeProperty: Int {
return
}
}
方法
实例方法和函数完全一致,定义在类中。每个实例都有一个隐含的 self 属性指向自己本身。
结构体和枚举是值类型。默认情况下,值类型的属性不能在它的实例方法中被修改。此时你可以使用 mutating 关键子修饰某个方法使其可以修改结构体或者枚举的属性;并且该方法对属性的修改都会反应到原始属性值上(即修改的是原始属性值),还可以给它隐含的 self 属性赋予一个全新的实例,这个新实例在方法结束时会替换现存实例。
struct Point {
var x = 0.0, y = 0.0
mutating func moveByX(deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY }
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveByX(2.0, y: 3.0)
print("The point is now at (\(somePoint.x), \(somePoint.y))") // 打印 "The point is now at (3.0, 4.0)"
在可变方法中给 self 赋值。
struct Point {
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
self = Point(x: x + deltaX, y: y + deltaY)
}
}
枚举的可变方法可以把 self 设置为同一枚举类型中不同的成员:
enum TriStateSwitch {
case Off, Low, High
mutating func next() {
switch self {
case .Off:
self = .Low
case .Low:
self = .High
case .High:
self = .Off }
}
}
var ovenLight = TriStateSwitch.Low ovenLight.next()
// ovenLight 现在等于 .High ovenLight.next()
// ovenLight 现在等于 .Off
在类方法的 func 关键字之前加上关键字 static ,来指定类型方法,该类型方法通过类本身进行调用;类还可以用关键字 class 来允许子类重写父类的方法。
class SomeClass {
class func someTypeMethod() {
// 在这里实现类型方法
}
}
SomeClass.someTypeMethod()
在类型方法的方法体中, self 指向这个类型本身,而不是类型的某个实例。这意味着你可以用 self 来消除类型属性和类型方法参数之间的歧义。
下标
标可以定义在类、结构体和枚举中,是访问 合,列表或序列中元素的快捷方式。
定义下标使用 subscript 关键字,指定一个或多个输入参数和返回类型;与实例方法不同的是,下标可以设定为读写或只读。这种行为由 getter 和 setter 实现,有点类似计算型属性。
subscript(index: Int) -> Int {
get {
// 返回一个适当的 Int 类型的值
}
set(newValue) {
// 执行适当的赋值操作
}
}
下标可以接受任意数量任意类型的无默认值非输入输出参数,可以使用变量参数和可变参数;其返回值也可以是任意类型的。
一个类或结构体可以根据自身需要提供多个下标实现,使用下标时将通过入参的数量和类型进行区分,自动匹配合适的下标,这就是下标的重载。
struct Matrix {
let rows: Int, columns: Int
var grid: [Double]
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
grid = Array(count: rows * columns, repeatedValue: 0.0)
}
func indexIsValidForRow(row: Int, column: Int) -> Bool {
return row >= && row < rows && column >= && column < columns
}
subscript(row: Int, column: Int) -> Double {
get {
assert(indexIsValidForRow(row, column: column), "Index out of range")
return grid[(row * columns) + column]
}
set {
assert(indexIsValidForRow(row, column: column), "Index out of range")
grid[(row * columns) + column] = newValue
}
}
}
继承
一个类可以继承另一个类的方法,属性和其它特性。继承是类独有的特性,被继承的类叫超类,继承的类叫子类。
为了指明某个类的超类,将超类名写在子类名的后面,用冒号分隔:bsp;
class SomeClass: SomeSuperclass {
// 这里是子类的定义
}
可以通过关键字 override 重写子类继承来的实例方法,类方法,实例属性,或下标,定制自己的功能。
class Train: Vehicle {
// 重写父类Vehicle中的makeNoise方法
override func makeNoise() {
print("Choo Choo")
}
}
可以通过 super 关键字应用超类对象。
你可以重写继承来的实例属性或类型属性,提供自己定制的 getter 和 setter,或添加属性观察器使重写的属性可以观察属性值什么时候发生变化。
你可以将一个继承来的只读属性重写为一个读写属性,只需要在重写版本的属性里提供 getter 和 setter 即可。但是,你不可以将一个继承来的读写属性重写为一个只读属性。
你可以通过重写属性为一个继承来的属性添加属性观察器。这样一来,当继承来的属性值发生改变时,你就会被 通知到,无论那个属性原本是如何实现的。
・ 你不可以为继承来的常量存储型属性或继承来的只读计算型属性添加属性观察器。这些属性的值不可以被设置 的,所以,为它们提供 willSet 或 didSet 实现是不恰当
・ 你不可以同时提供重写的 setter 和重写的属性观察器。如果你想观察属性值的变化,并你已 经为那个属性提供了定制的 setter,那么你在 setter 中就可以观察到任何值变化了
你可以通过把方法,属性或下标标记为 final 来防止它们被重写
声明:该系列内容均来自网络或电子书籍,只做学习总结!
Swift学习笔记(10):类和结构体的更多相关文章
- swift学习笔记3——类、结构体、枚举
之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...
- swift学习笔记之-类和结构体
//类和结构体 import UIKit //类和结构体 /* 1.枚举enum.结构体struct和String.Array.Dictionary类型,都属于值传递类型,被赋值给新的常量或变量时传递 ...
- Swift学习笔记(11)--类与结构体
类与结构是编程人员在代码中会经常用到的代码块.在类与结构中可以像定义常量,变量和函数一样,定义相关的属性和方法以此来实现各种功能. 和其它的编程语言不太相同的是,Swift不需要单独创建接口或者实现文 ...
- 【Swift】学习笔记(八)——类和结构体
1.类和结构体的定义 <pre name="code" class="html">struct Resolution { var width = 0 ...
- 【c# 学习笔记】类与结构体的区别
由于类与结构体在语法和使用上都非常类似,导致我们这些初学者容易混淆.为更好理解,特做以下区分记录: ① 语法上的区别在于,定义类要使用关键词class,而定义结构体则使用关键词struct. ② 结构 ...
- Swift学习笔记:类和结构
一.类和结构的异同 类和结构有一些相似的地方.它们都能够: 1. 定义一些能够赋值的属性: 2. 定义具有功能性的方法 3. 定义下标.使用下标语法 4. 定义初始化方法来设置初始状态 5. 在原实现 ...
- swift 学习- 10 -- 类和结构体
// '类和结构体' 是人们构建代码所使用的一种通用且灵活的构造体, 我们可以使用完全相同的语法规则来为 '类和结构体' 定义属性 (变量 和 常量) 和添加方法, 从而扩展 类和结构体 的功能 // ...
- 【Swift学习】Swift编程之旅---类和结构体(十三)
与其他编程语言所不同的是,Swift 并不要求你为自定义类和结构去创建独立的接口和实现文件.你所要做的是在一个单一文件中定义一个类或者结构体,系统将会自动生成面向其它代码的外部接口. 注意:通常一个类 ...
- Bash脚本编程学习笔记07:循环结构体
本篇中涉及到算术运算,使用了$[]这种我未在官方手册中见到的用法,但是确实可用的,在此前的博文<Bash脚本编程学习笔记03:算术运算>中我有说明不要使用,不过自己忘记了.大家还是尽量使用 ...
- Bash脚本编程学习笔记06:条件结构体
简介 在bash脚本编程中,条件结构体使用if语句和case语句两种句式. if语句 单分支if语句 if TEST; then CMD fi TEST:条件判断,多数情况下可使用test命令来实现, ...
随机推荐
- Laravel-事件简单使用
Laravel-事件简单使用 标签(空格分隔): php, laravel 注册事件和监听器 生成事件和监听器:php artisan event:generate key => 事件 valu ...
- ITWorld:2014年全球最杰出的14位编程天才
近日,ITWorld 整理全球最杰出的 14 位程序员,一起来看下让我们膜拜的这些大神都有哪些?(排名不分先后) 1.Jon Skeet 个人名望:程序技术问答网站 Stack Overflow 总排 ...
- Android GreenDao 使用教程
上一篇 总结了grendao 环境搭建以及简单的增删查改,接下来将全面解析框架的使用,基于上篇的orm模型(Note)数据库讲解 GreenDao的插入: 插入的方式有很多: daoSession.g ...
- CommandType.Text
CommandType.Text代表执行的是SQL语句CommandType.StoreProcedure代表执行的是存储过程CommandType代表要执行的类型 //返回DataTable的SQL ...
- DB2导出表结构、表数据小结
一.DB2命令行导出数据库全库表结构 ① Win+R进入到DB2安装目录的BIN目录下,执行命令:DB2CMD,进入到DB2 CLP窗口. 命令:DB2CMD ② 创建一个data文件夹 命令:MKD ...
- Caffe CommonLayer分析
Caffe CommonLayer分析 \(Caffe\)中包含了很多通用的功能层,包含了\(concat\),\(slice\),\(split\),\(crop\),\(flip\),\(scal ...
- map————两个数组的交集(2)
class Solution { public: vector<int> intersect(vector<int>& nums1, vector<int> ...
- [Vue warn]: Invalid prop: custom validator check failed for prop "type".
遇到错误如下, [Vue warn]: Invalid prop: custom validator check failed for prop "type". found in ...
- 小程序(Wepy)--生成海报图片
对于小程序的分享, 除了分享给朋友, 好友群,是可以直接做到的, 但是要想扩大推广范围, 通过生成海报图片, 将自己小程序码带进去,应该是目前我所知的好办法了. 但是海报也不是那么好搞.之前自己手写出 ...
- s5pv210 fimc 之 fimc-dev.c
fimc-dev.c 是Samsung FIMC 设备的V4L2 驱动.上层应用直接操作这个设备,进行capture,图片处理,以及overlay输出 http://blog.csdn.net/cxw ...