属性、方法以及继承

This commit is contained in:
2022-01-10 16:40:57 +08:00
parent 8de826239b
commit ad97b181bd
21 changed files with 501 additions and 1 deletions

View File

@@ -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()

View File

@@ -216,3 +216,122 @@ print(circleA.radius)
* 在属性定义时设置初始值不会触发 `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()
```

View File

@@ -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>

View 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
}
}
}

View 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)
```

View 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>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Timeline
version = "3.0">
<TimelineItems>
</TimelineItems>
</Timeline>

View 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])

View 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
```

View 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>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,3 @@
import UIKit
var greeting = "Hello, playground"

View 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>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Timeline
version = "3.0">
<TimelineItems>
</TimelineItems>
</Timeline>

View File

@@ -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>