类的介绍和定义
- Swift也是一门面向对象的开发语言。
- 面向对象的基础就是类,类产生对象。
- Swift如何定义类:
- class关键字定义类
class 类名: SuperClass { //定义属性和方法
}
* 使用注意:
* 定义类的时候,可以没有父类,那么该类就是根类
* 通常情况下定义定义类时,继承自NSObject
**如何定义类的属性**
* Swift中类的属性有多种:
* 存储属性:存储实例的常量和变量
* 计算属性:通过某种方式计算出来的属性
* 类属性:与整个类相关的属性
* 存储属性
```
class person: NSObject{
//存储属性
var age = 0
var name: String?
}
let child = person()
child.age = 18
child.name = "小明"
if let name = child.name {
print("\(name)今年\(child.age)了")
}
//结果:小明今年18了
```
* 计算属性
在类中声明的计算属性,这个属性可以由类中定义的函数来完成,但是苹果官方并不见这种实现方式,因为计算属性的方式更加简单明了,下面就来实现以下某个人的在某段时间内完成跑步的平均时速。
class person: NSObject{
var time = 2
var startSpeed = 10.0
var hightSpeed = 20.0
var endSpeed = 5.0
//推荐
var averageSpeed: Double {
return (startSpeed + hightSpeed + endSpeed) * 0.5
}
//不推荐
func averageSpeedFunction() -> Double {
return (startSpeed + hightSpeed + endSpeed) * 0.5
}
}
let child = person()
child.averageSpeedFunction()
child.averageSpeed
* 类属性
类属性是和整个类相关的属性,而且是通过类名来访问。常见于单例!
class person: NSObject{
//定义某个人有书籍的数量
static var book = 0
}
person.book = 2
//结果:2
**类的构造函数**
* 构造函数
* 构造函数类似于OC中的初始化方法:init方法
* 默认情况下创建某个类时,必然会调用一个构造函数
* 即便开发者没有构建构造函数,编译器也会提供默认的构造函数
* 如果继承自NSObject可以对父类的构造函数进行重写
* 构造函数的基本使用
* 类的属性必须有值
* 如未在定义时初始化值,可以在构造函数中赋值,通过传递参数,初始化类对象。
```
class person: NSObject{
var name: String?
var height = 0.0
//重写父类的构造方法
//如果重写父类的构造方法,在实例化此类时,Xcode会提示这个方法,如果未重写,Xcode只会提示,我们自定义的构造方法!
override init(){
super.init()
}
//自定义构造方法
init(name: String, height: Double) {
self.name = name
self.height = height
}
}
let child = person(name: "小明", height: 1.88)
child.name
child.height
//结果:小明 1.88
```
* 通过字典参数实例化类对象
```
class person: NSObject{
var name: String?
var height = 0.0
//重写父类的构造方法
override init(){
super.init()
}
//自定义构造方法
init(name: String, height: Double) {
self.name = name
self.height = height
}
init(dict: [String : AnyObject]) {
//此种写法会报错,因为从字典中取出的值为AnyObject?可选类型,直接赋值会报错!
//self.name = dict["name"]
//self.height = dict["height"]
//解决方法1:
//as? 转换符 将as?左侧的类型转换成as?右侧的类型的可选类型
name = dict["name"] as? String
//as! 转换符 将as!左侧的类型转换成as! 右侧的类型的可选类型
height = dict["height"] as! Double
//但是此种写法同时有带来了新的问题,强制解包是很危险的操作,会造成程序crash
//解决方法2:
name = dict["name"] as? String
//可选绑定
if let tempHeight = dict["height"] as? Double {
height = tempHeight
}
}
}
let child = person(dict: ["name":"小明" as AnyObject, "height": 1.90 as AnyObject])
```
利用KVC实现构造函数实现
```
class person: NSObject{
var name: String?
var height = 0.0
//重写父类的构造方法
override init(){
super.init()
}
//自定义构造方法
init(name: String, height: Double) {
self.name = name
self.height = height
}
//KVC
init(dict: [String : AnyObject]) {
super.init()
setValuesForKeys(dict)
}
//防止传入的字典存在未知的键值->报错
override func setValue(_ value: Any?, forUndefinedKey key: String) {}
}
let child = person(dict: ["name":"小明" as AnyObject, "height": 1.90 as AnyObject, "weight": 100 as AnyObject])
child.name
child.height
//结果:小明 1.9
```
**类的属性监听器**
* 在OC中我们可以重写set方法来监听属性的改变
* Swift中可以通过属性观察者来监听和响应属性的改变
* 通常监听存储属性和类属性
* 通过设置以下方法来定义观察者
* willSet:将在属性值即将改变时调用
* didSet:将在属性值改变后调用
class person: NSObject{
var name: String?{
willSet{
print("\(name)")
}
didSet{
print("\(name)")
}
}
}
let child = person()
child.name = "小明"
**结构体的介绍和定义**
结构体与类存在很多共同点:
* 定义属性用于存储值
* 定义方法用于提供功能
* 定义下标操作使得可以通过下标语法来访问实例所包含的值
* 定义构造器用于生成初始化值
* 通过扩展以增加默认实现的功能
* 实现协议以提供某种标准功能
* Swift中如何定义结构体:
* struct关键字定义结构体
struct 结构体名{
//结构体属性or方法
}
**结构体实例化**
结构体实例化和类实例化非常相似:
struct SomeStruct{
//结构体属性or方法
var width = 0
var height = 0
}
//实例化结构体
var someStruct = SomeStruct()
在Swift中,结构体可以直接修改结构体的子属性的值,这点是与OC不同之处!
import UIKit
struct SomeStruct{
//结构体属性or方法
var width = 0
var height = 0
}
var someStruct = SomeStruct()
someStruct.height = 100
someStruct.height
//结果:someStruct.height值为100
**结构体的逐一构造器**
结构体存在逐一构造器,而类中默认是不存在的!我们可以自定义构造函数来完成逐一构造器,上述类的自定义构造方法其实就是自定义的逐一构造器方法!
struct SomeStruct{
//结构体属性or方法
var width = 0
var height = 0
}
var someStruct = SomeStruct(width: 66, height: 88)
someStruct.height
//结果:88
someStruct.width
//结果:66
**结构体与类之间的选择**
�结构体总是通过值传递(值类型),类总是通过引用传递(引用类型)!
按照通用的准则,当符合一条或多条以下条件时,请考虑构建结构体:
* 该数据结构的主要目的是用来封装少量相关简单数据值。
* 有理由预计该数据结构的实例在被赋值或传递时,封装的数据将会被拷贝而不是被引用。
* 该数据结构中储存的值类型属性,也应该被拷贝,而不是被引用。
* 该数据结构不需要去继承另一个既有类型的属性或者行为。
######注意:
在Swift中字符串、数组、字典均为结构体的形式实现(OC中均为类的形式实现)。拷贝行为看起来似乎总会发生。然而,Swift 在幕后只在绝对必要时才执行实际的拷贝。Swift 管理所有的值拷贝以确保性能最优化,所以你没必要去回避赋值来保证性能最优化。
Zeb
参考地址:https://github.com/numbbbbb/the-swift-programming-language-in-chinese