func methodGrammar() {
//方法是和特定类型相关的函数, Swift 中 Class, struct, enum 都可以定义实例方法和类型方法
//Class 的方法可以继承, struct, enum 方法不可以继承
//struct, enum 是值类型, 属性默认不能修改, 要修改使用 mutating 关键字
/*
class 和 static 相同点:
1.可以修饰方法
2.可以修饰计算属性
class 和 static 不同点:
属性:
class 不能修饰存储属性,static 可以修饰存储属性, static修饰的存储属性称为静态变量(常量)
class 修饰的计算属性可以被重写,static 修饰的不能被重写
class 修饰的计算属性被重写时,可以使用static 让其变为静态属性
方法:
class 只能在 Class 中使用,但是static 可以在 Class, struct, enum中使用
class 修饰的方法可以被重写,static 修饰的不能被重写
class 修饰的方法被重写时,可以使用static 让方法变为静态方法
*/
//1. 实例方法
class Counter {
var count: Int = 0
func increment() {
count += 1
}
func incrementBy(by amount: Int) {
count += amount
}
func reset() {
count = 0
}
}
//和调用属性一样,用点语法调用实例方法
let counter = Counter()
counter.increment()
counter.incrementBy(by: 5)
counter.reset()
//2. self
//上例 counter 中的已知 property 和 method 指向 self, self 可以省略不写
//使用 self 的主要场景: 当实例方法的参数名和实例的 property 名字相同时, 使用 self 区分
struct Point {
var x = 0.0, y = 0.0
func isToTheRightOf(x: Double) -> Bool {
return self.x > x
}
}
let somePoint = Point(x: 4.0, y: 5.0)
if somePoint.isToTheRightOf(x: 1.0) {
print("This point is to the right of the line where x == 1.0")
}
//3. 修改实例方法中的值类型(struct, enum)
//struct 和 enum 是值类型的, 值类型的实例方法中默认 property 不能修改
//如果想要修改 struct, enum 的属性, 可以使用关键字 mutating
struct AnotherPoint {
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
var anotherPoint = AnotherPoint(x: 1.0, y: 2.0)
anotherPoint.moveBy(x: 2.0, y: 3.0)
//注意: 不能调用常量结构体类型的 mutating 方法, 即使要改变的 property 是 var 类型的
//4. 在 mutating 方法内给 self 赋值
//mutating 方法可以将实例赋给 self
struct yetAnotherPoint {
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
self = yetAnotherPoint(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()
//self = high
ovenLight.next()
//self = off
//5. 类型方法(Type Methods)
//Class, struct, enum 都有类型方法
//使用关键字 static 表明类型方法
//static 修饰 Class 中定义的类型方法, 则子类对应的类型方法不可重写
//class 修饰 Class 中定义的类型方法, 子类对应的类型方法可以重写
class SomeClass {
//类型方法
class func someTypeMethod() {
//1. type method 中, self 表示类.使用 self的场景和 Instance Methods类似
//2. type method 中, 可以使用调用另一个 type method
var light = TriStateSwitch.low
light.next()
}
}
class AClass: SomeClass {
override class func someTypeMethod() {
print("adfafaf")
}
}
SomeClass.someTypeMethod()
struct LevelTracker {
static var highestUnlockedLevel = 1
var currentLevel = 1
//类型方法
static func unlock(_ level: Int) {
if level > highestUnlockedLevel { highestUnlockedLevel = level }
}
//类型方法
static func isUnlocked(_ level: Int) -> Bool {
return level <= highestUnlockedLevel
}
//@discardableResult 结果可忽略, 添加后不使用返回值不会有警告
//实例方法
@discardableResult mutating func advance(to level: Int) -> Bool {
if LevelTracker.isUnlocked(level) {
currentLevel = level
return true
}else {
return false
}
}
}
class Player {
var tracker = LevelTracker()
let playerName: String
func complete(level: Int) {
LevelTracker.unlock(level + 1)
tracker.advance(to: level + 1)
}
init(name: String) {
playerName = name
}
}
//完成第一级
var player = Player(name: "Argyrios")
player.complete(level: 1)
print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
// Prints "highest unlocked level is now 2"
//试图进入没有解锁的等级
player = Player(name: "Beto")
if player.tracker.advance(to: 6) {
print("player is now on level 6")
} else {
print("level 6 has not yet been unlocked")
}
// Prints "level 6 has not yet been unlocked"
}
func handleThrow() {
//如果在调用系统某一方法时 ,该方法最后有一个throws. 说明该方法会抛出异常,如果一个方法会抛出异常,那么需要对异常进行处理
//在Swift中提供三种处理异常方式
//方式一: try方式 程序员手动捕捉异常
do {
try FileManager.default.contentsOfDirectory(atPath: NSHomeDirectory())
}catch{
//error异常对象
print(error)
}
//方式二: try?方式 系统帮助我们处理异常 ,如果该方法出现了异常, 则方法返回nil ,如果没有异常,则返回对应的对象
//推荐方式
//安全校验
guard let content = try? FileManager.default.contentsOfDirectory(atPath: NSHomeDirectory()) else{
return
}
//方式三 : try!方式 直接告诉系统,该方法没有异常,如果该方法出现了错误,直接崩溃
let content1 = try! FileManager.default.contentsOfDirectory(atPath: NSHomeDirectory())
}