属性、方法以及继承
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import UIKit
|
import UIKit
|
||||||
|
import CoreGraphics
|
||||||
|
|
||||||
|
|
||||||
struct Circle {
|
struct Circle {
|
||||||
@@ -100,3 +101,70 @@ struct CircleA {
|
|||||||
var circleA = CircleA()
|
var circleA = CircleA()
|
||||||
circleA.radius = 10.5
|
circleA.radius = 10.5
|
||||||
print(circleA.radius)
|
print(circleA.radius)
|
||||||
|
|
||||||
|
struct Shape {
|
||||||
|
var width: Int
|
||||||
|
var side: Int {
|
||||||
|
willSet {
|
||||||
|
print("willSetSide", newValue)
|
||||||
|
}
|
||||||
|
didSet {
|
||||||
|
print("didSetSide", oldValue, side)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var girth: Int {
|
||||||
|
set {
|
||||||
|
width = newValue / side
|
||||||
|
print("setGirth", newValue)
|
||||||
|
}
|
||||||
|
get {
|
||||||
|
print("getGirth")
|
||||||
|
return width * side
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func show() {
|
||||||
|
print("width=\(width), side=\(side), girth=\(girth)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func test(_ num: inout Int) {
|
||||||
|
num = 20
|
||||||
|
}
|
||||||
|
var s = Shape(width: 10, side: 4)
|
||||||
|
test(&s.width)
|
||||||
|
s.show()
|
||||||
|
print("----------")
|
||||||
|
test(&s.side)
|
||||||
|
s.show()
|
||||||
|
print("----------")
|
||||||
|
test(&s.girth)
|
||||||
|
s.show()
|
||||||
|
|
||||||
|
struct CarA {
|
||||||
|
static var count: Int = 0
|
||||||
|
init() {
|
||||||
|
CarA.count += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let c1 = CarA()
|
||||||
|
let c2 = CarA()
|
||||||
|
let c3 = CarA()
|
||||||
|
|
||||||
|
print(CarA.count)
|
||||||
|
|
||||||
|
|
||||||
|
// 单例模式
|
||||||
|
public class FileManager {
|
||||||
|
// 延迟初始化
|
||||||
|
public static let shared = FileManager()
|
||||||
|
// 禁止外部初始化
|
||||||
|
private init() {}
|
||||||
|
// 方法
|
||||||
|
func run() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileManager.shared.run()
|
||||||
|
|
||||||
|
@@ -215,4 +215,123 @@ print(circleA.radius)
|
|||||||
* 在初始化器中设置属性值不会触发 `willSet` 和 `didSet`
|
* 在初始化器中设置属性值不会触发 `willSet` 和 `didSet`
|
||||||
* 在属性定义时设置初始值不会触发 `willSet` 和 `didSet`
|
* 在属性定义时设置初始值不会触发 `willSet` 和 `didSet`
|
||||||
|
|
||||||
#### 全局变量/局部变量
|
#### 全局变量/局部变量
|
||||||
|
|
||||||
|
属性观察器、计算属性的功能,也可以应用在全局变量以及局部变量。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### inout
|
||||||
|
|
||||||
|
inout的本质就是引用传递(地址传递)
|
||||||
|
|
||||||
|
* 如果实参有物理内存地址,且没有设置属性观察器
|
||||||
|
* 直接将实参的内存地址传入函数(实参进行引用传递)
|
||||||
|
* 如果实参是计算属性或者设置了属性观察器
|
||||||
|
* 采取了CopyInCopyOut的做法
|
||||||
|
* 调用该函数时,先复制实参的值,产生副本【get】
|
||||||
|
* 将副本的内存地址传入函数(副本进行引用传递),在函数内部可以修改副本的值
|
||||||
|
* 函数返回后,再将副本的值覆盖实参的值【set】
|
||||||
|
|
||||||
|
```swift
|
||||||
|
struct Shape {
|
||||||
|
// 没有设置属性观察器
|
||||||
|
var width: Int
|
||||||
|
// 设置属性观察器
|
||||||
|
var side: Int {
|
||||||
|
willSet {
|
||||||
|
print("willSetSide", newValue)
|
||||||
|
}
|
||||||
|
didSet {
|
||||||
|
print("didSetSide", oldValue, side)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var girth: Int {
|
||||||
|
set {
|
||||||
|
width = newValue / side
|
||||||
|
print("setGirth", newValue)
|
||||||
|
}
|
||||||
|
get {
|
||||||
|
print("getGirth")
|
||||||
|
return width * side
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func show() {
|
||||||
|
print("width=\(width), side=\(side), girth=\(girth)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func test(_ num: inout Int) {
|
||||||
|
num = 20
|
||||||
|
}
|
||||||
|
var s = Shape(width: 10, side: 4)
|
||||||
|
test(&s.width)
|
||||||
|
s.show()
|
||||||
|
print("----------")
|
||||||
|
test(&s.side)
|
||||||
|
s.show()
|
||||||
|
print("----------")
|
||||||
|
test(&s.girth)
|
||||||
|
s.show()
|
||||||
|
```
|
||||||
|
|
||||||
|
输出的结果
|
||||||
|
|
||||||
|
<img src="https://vip2.loli.io/2022/01/10/zbm3wBNgWu57EG8.png" alt="jiulinxiri_20220110114314" style="zoom:50%;" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 类型属性(Type Property)
|
||||||
|
|
||||||
|
类型属性主要是通过 `static` 定义类型属性,枚举类型也可以定义类型属性(存储类型属性、计算类型属性)
|
||||||
|
|
||||||
|
属性分类
|
||||||
|
|
||||||
|
* 实例属性(Instance Property): 只能通过实例去访问
|
||||||
|
* 存储实例属性 (Stored Instance Property): 存储在实例的内存中,每个实例都有 1 份
|
||||||
|
* 计算实例属性 (Computed Instance Property)
|
||||||
|
* 类型属性(Type Property): 只能通过类型去访问
|
||||||
|
* 存储类型属性(Stored Type Property): 整个程序运行的过程中,就只有 1 份内存(类似于全局变量)
|
||||||
|
* 存储类型属性默认就是 `lazy`,会在第一次使用的时候才初始化
|
||||||
|
* 就算被多个线程同时访问,保证只会初始化一次
|
||||||
|
* 存储类型属性可以是 `let`
|
||||||
|
* 计算类型属性(Computed Type Property)
|
||||||
|
|
||||||
|
```swift
|
||||||
|
struct CarA {
|
||||||
|
// 存储类属性
|
||||||
|
static var count: Int = 0
|
||||||
|
init() {
|
||||||
|
CarA.count += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let c1 = CarA()
|
||||||
|
let c2 = CarA()
|
||||||
|
let c3 = CarA()
|
||||||
|
|
||||||
|
print(CarA.count)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 单例模式
|
||||||
|
|
||||||
|
```swift
|
||||||
|
// 单例模式
|
||||||
|
public class FileManager {
|
||||||
|
// 延迟初始化
|
||||||
|
public static let shared = FileManager()
|
||||||
|
// 禁止外部初始化
|
||||||
|
private init() {}
|
||||||
|
// 方法
|
||||||
|
func run() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileManager.shared.run()
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Binary file not shown.
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>SchemeUserState</key>
|
||||||
|
<dict>
|
||||||
|
<key>10 属性 inout (Playground).xcscheme</key>
|
||||||
|
<dict>
|
||||||
|
<key>isShown</key>
|
||||||
|
<false/>
|
||||||
|
<key>orderHint</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
41
11 方法.playground/Contents.swift
Normal file
41
11 方法.playground/Contents.swift
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import Cocoa
|
||||||
|
|
||||||
|
|
||||||
|
class Car {
|
||||||
|
static var cout = 0
|
||||||
|
init() {
|
||||||
|
Car.cout += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
static func getCount() -> Int {cout}
|
||||||
|
}
|
||||||
|
|
||||||
|
let c0 = Car()
|
||||||
|
let c1 = Car()
|
||||||
|
let c2 = Car()
|
||||||
|
// 3
|
||||||
|
print(Car.getCount())
|
||||||
|
|
||||||
|
|
||||||
|
struct Point {
|
||||||
|
var x = 0.0, y = 0.0
|
||||||
|
mutating func moveBy(deltaX: Double, deltaY: Double) {
|
||||||
|
x += deltaX
|
||||||
|
y += deltaY
|
||||||
|
// self = Point(x: x + deltaX, y: y + deltaY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum StateSwitch {
|
||||||
|
case low, middle, high
|
||||||
|
mutating func next() {
|
||||||
|
switch self {
|
||||||
|
case .low:
|
||||||
|
self = .middle
|
||||||
|
case .middle:
|
||||||
|
self = .high
|
||||||
|
case .high:
|
||||||
|
self = .low
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
79
11 方法.playground/Resources/README.md
Normal file
79
11 方法.playground/Resources/README.md
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
### 方法
|
||||||
|
|
||||||
|
枚举、结构体、类都可以定义实例方法、类方法
|
||||||
|
|
||||||
|
* 实例方法(Instance Method)
|
||||||
|
* 通过实例调用
|
||||||
|
* 类方法(Type Method)
|
||||||
|
* 通过类型调用,用 `static` 或者 `class` 关键字定义
|
||||||
|
|
||||||
|
```swift
|
||||||
|
class Car {
|
||||||
|
static var cout = 0
|
||||||
|
init() {
|
||||||
|
Car.cout += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
static func getCount() -> Int {
|
||||||
|
// 等价于 self.cout、Car.cout
|
||||||
|
cout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let c0 = Car()
|
||||||
|
let c1 = Car()
|
||||||
|
let c2 = Car()
|
||||||
|
// 3
|
||||||
|
print(Car.getCount())
|
||||||
|
```
|
||||||
|
|
||||||
|
#### self
|
||||||
|
|
||||||
|
* 在实例方法中代表实例
|
||||||
|
* 在类型方法中代表类型
|
||||||
|
|
||||||
|
#### mutating
|
||||||
|
|
||||||
|
结构体和枚举是**值类型**,默认情况下,值类型的属性不能被自身的实例方法修改。在 `func` 关键字前加 `mutating` 可以允许这种修改行为。
|
||||||
|
|
||||||
|
```swift
|
||||||
|
struct Point {
|
||||||
|
var x = 0.0, y = 0.0
|
||||||
|
mutating func moveBy(deltaX: Double, deltaY: Double) {
|
||||||
|
x += deltaX
|
||||||
|
y += deltaY
|
||||||
|
// self = Point(x: x + deltaX, y: y + deltaY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum StateSwitch {
|
||||||
|
case low, middle, high
|
||||||
|
mutating func next() {
|
||||||
|
switch self {
|
||||||
|
case .low:
|
||||||
|
self = .middle
|
||||||
|
case .middle:
|
||||||
|
self = .high
|
||||||
|
case .high:
|
||||||
|
self = .low
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### @discardableResult
|
||||||
|
|
||||||
|
在 `func` 前面加个 `@discardableResult` ,可以消除:函数调用后返回值未被使用的警告⚠
|
||||||
|
|
||||||
|
```swift
|
||||||
|
struct Point {
|
||||||
|
var x = 0.0, y = 0.0
|
||||||
|
@discardableResult mutating
|
||||||
|
func moveX(deltaX: Double) -> Double {
|
||||||
|
x += deltaX
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var p = Point()
|
||||||
|
p.moveX(deltaX: 10)
|
||||||
|
```
|
4
11 方法.playground/contents.xcplayground
Normal file
4
11 方法.playground/contents.xcplayground
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<playground version='5.0' target-platform='macos' buildActiveScheme='true' importAppTypes='true'>
|
||||||
|
<timeline fileName='timeline.xctimeline'/>
|
||||||
|
</playground>
|
7
11 方法.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
11 方法.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
BIN
11 方法.playground/playground.xcworkspace/xcuserdata/jiulinxiri.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
BIN
11 方法.playground/playground.xcworkspace/xcuserdata/jiulinxiri.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
Binary file not shown.
6
11 方法.playground/timeline.xctimeline
Normal file
6
11 方法.playground/timeline.xctimeline
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Timeline
|
||||||
|
version = "3.0">
|
||||||
|
<TimelineItems>
|
||||||
|
</TimelineItems>
|
||||||
|
</Timeline>
|
32
12 下标.playground/Contents.swift
Normal file
32
12 下标.playground/Contents.swift
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import Cocoa
|
||||||
|
|
||||||
|
class Point {
|
||||||
|
var x = 0.0, y = 0.0
|
||||||
|
subscript(index: Int) -> Double {
|
||||||
|
set {
|
||||||
|
if index == 0 {
|
||||||
|
x = newValue
|
||||||
|
} else if index == 1 {
|
||||||
|
y = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
if index == 0 {
|
||||||
|
return x
|
||||||
|
} else if index == 1 {
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var p = Point()
|
||||||
|
p[0] = 11.1
|
||||||
|
p[1] = 22.2
|
||||||
|
print(p.x)
|
||||||
|
print(p.y)
|
||||||
|
print(p[0])
|
||||||
|
print(p[1])
|
81
12 下标.playground/Resources/README.md
Normal file
81
12 下标.playground/Resources/README.md
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
### 下标(subscript)
|
||||||
|
|
||||||
|
使用 `subscript` 可以给任意类型(枚举、结构体、类)增加下标功能。`subscript` 的语法类似于实例方法、计算属性,本质就是方法(函数)
|
||||||
|
|
||||||
|
```swift
|
||||||
|
class Point {
|
||||||
|
var x = 0.0, y = 0.0
|
||||||
|
subscript(index: Int) -> Double {
|
||||||
|
set {
|
||||||
|
if index == 0 {
|
||||||
|
x = newValue
|
||||||
|
} else if index == 1 {
|
||||||
|
y = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
if index == 0 {
|
||||||
|
return x
|
||||||
|
} else if index == 1 {
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var p = Point()
|
||||||
|
p[0] = 11.1
|
||||||
|
p[1] = 22.2
|
||||||
|
print(p.x)
|
||||||
|
print(p.y)
|
||||||
|
print(p[0])
|
||||||
|
print(p[1])
|
||||||
|
```
|
||||||
|
|
||||||
|
`subscript` 中定义的返回值类型决定了
|
||||||
|
|
||||||
|
* get方法的返回值类型
|
||||||
|
* set方法中newValue的类型
|
||||||
|
|
||||||
|
`subscript` 可以接受多个参数,并且类型任意
|
||||||
|
|
||||||
|
#### 下标细节
|
||||||
|
|
||||||
|
1. `subscripte` 可以没有 `set` 方法,但是必须有 `get` 方法
|
||||||
|
|
||||||
|
2. 如果只有 `get` 方法,可以省略 `get`
|
||||||
|
|
||||||
|
3. 可以设置参数标签
|
||||||
|
|
||||||
|
```swift
|
||||||
|
class Point {
|
||||||
|
var x = 0.0, y = 0.0
|
||||||
|
subscript(index i: Int) -> Double {
|
||||||
|
if i == 0 {
|
||||||
|
return x
|
||||||
|
} else if i == 1 {
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var p = Point()
|
||||||
|
p.y = 22.2
|
||||||
|
print(p[index: 1]) // 22.2
|
||||||
|
```
|
||||||
|
|
||||||
|
4. 下标可以是类型方法
|
||||||
|
|
||||||
|
```swift
|
||||||
|
class Sum {
|
||||||
|
static subscript(v1: Int, v2: Int) -> Int {
|
||||||
|
return v1 + v2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print(Sum[10, 20]) // 30
|
||||||
|
```
|
||||||
|
|
||||||
|
|
4
12 下标.playground/contents.xcplayground
Normal file
4
12 下标.playground/contents.xcplayground
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<playground version='5.0' target-platform='macos' buildActiveScheme='true' importAppTypes='true'>
|
||||||
|
<timeline fileName='timeline.xctimeline'/>
|
||||||
|
</playground>
|
7
12 下标.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
12 下标.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
BIN
12 下标.playground/playground.xcworkspace/xcuserdata/jiulinxiri.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
BIN
12 下标.playground/playground.xcworkspace/xcuserdata/jiulinxiri.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
Binary file not shown.
3
13 继承.playground/Contents.swift
Normal file
3
13 继承.playground/Contents.swift
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import UIKit
|
||||||
|
|
||||||
|
var greeting = "Hello, playground"
|
4
13 继承.playground/contents.xcplayground
Normal file
4
13 继承.playground/contents.xcplayground
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<playground version='5.0' target-platform='ios' buildActiveScheme='true' executeOnSourceChanges='false' importAppTypes='true'>
|
||||||
|
<timeline fileName='timeline.xctimeline'/>
|
||||||
|
</playground>
|
7
13 继承.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
13 继承.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
BIN
13 继承.playground/playground.xcworkspace/xcuserdata/jiulinxiri.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
BIN
13 继承.playground/playground.xcworkspace/xcuserdata/jiulinxiri.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
Binary file not shown.
6
13 继承.playground/timeline.xctimeline
Normal file
6
13 继承.playground/timeline.xctimeline
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Timeline
|
||||||
|
version = "3.0">
|
||||||
|
<TimelineItems>
|
||||||
|
</TimelineItems>
|
||||||
|
</Timeline>
|
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>SchemeUserState</key>
|
||||||
|
<dict>
|
||||||
|
<key>13 继承 (Playground).xcscheme</key>
|
||||||
|
<dict>
|
||||||
|
<key>isShown</key>
|
||||||
|
<false/>
|
||||||
|
<key>orderHint</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
Reference in New Issue
Block a user