属性、方法以及继承
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import UIKit
|
||||
import CoreGraphics
|
||||
|
||||
|
||||
struct Circle {
|
||||
@@ -100,3 +101,70 @@ struct CircleA {
|
||||
var circleA = CircleA()
|
||||
circleA.radius = 10.5
|
||||
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`
|
||||
|
||||
#### 全局变量/局部变量
|
||||
#### 全局变量/局部变量
|
||||
|
||||
属性观察器、计算属性的功能,也可以应用在全局变量以及局部变量。
|
||||
|
||||
|
||||
|
||||
#### 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