本文是个比较简单的学习笔记,更详细的内容见 Swift官方文档
Swift标准库用 < 和 == 运算符定义了 >、>=、<=,所以实现 Comparable 的 < 运算符就会自动得到这些运算符的实现,实际上 Comparable 继承自 Equatable,所以 == 运算也是必须实现的,以下是示例代码
- struct Point: Comparable, CustomStringConvertible {
- let x: Int
- let y: Int
-
- var description: String {
- return "Point(\(x), \(y))"
- }
-
-
- static func ==(lhs: Point, rhs: Point) -> Bool {
- return lhs.x == rhs.x && lhs.y == rhs.y
- }
-
- static func <(lhs: Point, rhs: Point) -> Bool {
- return lhs.x < rhs.x && lhs.y < rhs.y
- }
-
- static func + (left: Point, right: Point) -> Point {
- return Point(x: left.x + right.x, y: left.y + right.y)
- }
- }
-
- let a = Point(x: 3, y: 4)
- let b = Point(x: 3, y: 4)
- let abEqual = (a == b)
- a != b
-
- let c = Point(x: 2, y: 6)
- let d = Point(x: 3, y: 7)
- c == d
- c < d
- c <= d
- c > d
- c >= d
-
- c + d
-
-
- class Person: Equatable {
- let name: String
- let age: Int
- weak var brother: Person?
-
- init(name: String, age: Int) {
- self.name = name
- self.age = age
- }
-
- static func ==(lhs: Person, rhs: Person) -> Bool {
- return lhs.name == rhs.name
- }
- }
-
- let p1 = Person(name: "JJF", age: 33)
- let p2 = Person(name: "JZF", age: 36)
- var people = [p1, p2]
- if let p1Index = people.firstIndex(where: { $0 == p2 }) {
- print(p1Index)
- }
-
- //自定义运算符
- infix operator +++
-
- func +++(lhs: Person, rhs: Person) {
- lhs.brother = rhs
- rhs.brother = lhs
- }
- p1 +++ p2
- p1.brother?.name
- p2.brother?.name
- import Foundation
-
- let date = Date.now
-
- let dateFormatter = DateFormatter()
- //dateFormatter.locale = Locale(identifier: "zh_CN")
- dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
-
- // typealias TimeInterval = Double
- // A number of seconds.
- // TimeInterval 是 Double 类型,单位是秒,可精确到微秒
- //时间戳,1970到现在的毫秒数
- let timestamp = Int(date.timeIntervalSince1970 * 1000)
- print("timestamp = \(timestamp)")
-
- //取当前时间的年/月/日/时/分/秒/毫秒
- var calendar = Calendar.current
- let year = calendar.component(.year, from: date)
- let month = calendar.component(.month, from: date)
- let day = calendar.component(.day, from: date)
- let hour = calendar.component(.hour, from: date)
- let minute = calendar.component(.minute, from: date)
- let second = calendar.component(.second, from: date)
- let milliSecond = calendar.component(.nanosecond, from: date) / 1000_000
- print("\(year)-\(String(format: "%02D", month))-\(String(format: "%02D", day)) \(String(format: "%02D", hour)):\(String(format: "%02D", minute)):\(String(format: "%02D", second)).\(String(format: "%03D", milliSecond))")
-
- //使用 DateFormatter 格式化时间
- print("\(dateFormatter.string(from: date))")
-
-
- let str = "Hello World!"
- let start = str.index(str.startIndex, offsetBy: 6)
- let end = str.index(str.startIndex, offsetBy: 11)
- let substr = String(str[start..<end])
- print(substr)
- enum Token {
- case number(Int)
- case plus
- }
-
- class Lexer {
- enum Error: Swift.Error {
- case invalidCharacter(Character)
- }
- let input: String
- var position: String.Index
-
- init(input: String) {
- self.input = input
- self.position = self.input.startIndex
- }
-
- func peek() -> Character? {
- guard position < input.endIndex else {
- return nil
- }
- return input[position]
- }
-
- func advance() {
- //断言只在调试模式下生效,发布模式下可使用 precondition(_:_:) 替代
- assert(position < input.endIndex, "Cannot advance past endIndex!")
- position = input.index(after: position)
- }
-
- func lex() throws -> [Token] {
- var tokens = [Token]()
- while let nextCharacter = peek() {
- switch nextCharacter {
- case "0"..."9":
- tokens.append(.number(getNumber()))
- case "+":
- tokens.append(.plus)
- advance()
- case " ":
- advance()
- default:
- throw Lexer.Error.invalidCharacter(nextCharacter)
- }
- }
- return tokens
- }
-
- func getNumber() -> Int {
- var value = 0
-
- while let nextCharacter = peek() {
- switch nextCharacter {
- case "0"..."9":
- let digitValue = Int(String(nextCharacter))!
- value = 10 * value + digitValue
- advance()
- default:
- return value
- }
- }
- return value
- }
- }
-
-
- class Parser {
- enum Error: Swift.Error {
- case unexpectedEndOfInput
- case invalidToken(Token)
- }
- let tokens: [Token]
- var position = 0
-
- init(tokens: [Token]) {
- self.tokens = tokens
- }
-
- func nextToken() -> Token? {
- guard position < tokens.count else {
- return nil
- }
- let token = tokens[position]
- position += 1
- return token
- }
-
- func getNumber() throws -> Int {
- guard let token = nextToken() else {
- throw Parser.Error.unexpectedEndOfInput
- }
- switch token {
- case .number(let value):
- return value
- case .plus:
- throw Parser.Error.invalidToken(token)
- }
- }
-
- func parse() throws -> Int {
- var value = try getNumber()
-
- while let token = nextToken() {
- switch token {
- case .plus:
- let nextNumber = try getNumber()
- value += nextNumber
- case .number:
- throw Parser.Error.invalidToken(token)
- }
- }
- return value
- }
- }
-
- func evaluate(_ input: String) {
- print("Evaluating: \(input)")
- let lexer = Lexer(input: input)
- // let tokens = try! lexer.lex()//强制执行可能抛出错误的方法,发生错误时触发陷阱
- // guard let tokens = try? lexer.lex() else {
- // print("Lexing failed, but I don't know why")
- // return
- // }
- do {
- let tokens = try lexer.lex()
- print("Lexer ouput: \(tokens)")
- let parser = Parser(tokens: tokens)
- let value = try parser.parse()
- print(value)
- } catch Lexer.Error.invalidCharacter(let character) {
- print("Input contained an invalid character: \(character)")
- } catch Parser.Error.unexpectedEndOfInput {
- print("Unexpected end of input during parsing")
- } catch Parser.Error.invalidToken(let token) {
- print("Invalid token during parsing: \(token)")
- } catch {
- print("An error occurred: \(error)")
- }
- }
- evaluate("10 + 3 + 5 +")
- typealias Velocity = Double
-
- extension Velocity {
- var kph: Velocity { return self * 1.60934 }
- var mph: Velocity { return self }
- }
-
- protocol Vehicle {
- var topSpeed: Velocity { get }
- var numberOfDoors: Int { get }
- var hasFlatbed: Bool { get }
- }
-
- struct Car {
- let make: String
- let model: String
- let year: Int
- let color: String
- let nickname: String
- var gasLevel: Double {
- willSet {
- precondition(newValue <= 1.0 && newValue >= 0.0, "New value must between 0 and 1.")
- }
- }
- }
-
- //利用拓展使 Car 实现协议
- extension Car: Vehicle {
- var topSpeed: Velocity { return 180 }
- var numberOfDoors: Int { return 4 }
- var hasFlatbed: Bool { return false }
- }
-
- //利用拓展给 Car 增加初始化方法,这样会保留默认的成员初始化方法
- extension Car {
- init(make: String, model: String, year: Int) {
- self.init(make: make, model: model, year: year, color: "Black", nickname: "N/A", gasLevel: 1.0)
- }
- }
-
- var c = Car(make: "Ford", model: "Fusion", year: 2013)
-
- extension Car {
- enum Kind {
- case coupe, sedan
- }
- var kind: Kind {
- if numberOfDoors == 2 {
- return .coupe
- } else {
- return .sedan
- }
- }
- }
- c.kind
-
- extension Car {
- mutating func emptyGas(by amount: Double) {
- precondition(amount <= 1 && amount > 0, "Amount to remove must be between 0 and 1.")
- gasLevel -= amount
- }
-
- mutating func fillGas() {
- gasLevel = 1.0
- }
- }
- c.emptyGas(by: 0.3)
- c.gasLevel
- c.fillGas()
- c.gasLevel
- protocol Exercise: CustomStringConvertible {
- var name: String { get }
- var caloriesBurned: Double { get } //消耗的卡路里
- var minutes: Double { get }//锻炼的时长
- }
-
- extension Exercise {
- var description: String {
- return "Exercise(\(name), burned \(caloriesBurned) calories in \(minutes) minutes)"
- }
- }
-
- extension Exercise {
- var title: String {
- return "\(name) - \(minutes) minutes"
- }
- }
-
- struct EllipticalWorkout: Exercise {
- let name: String = "Elliptical Workout"
- let title: String = "Workout using the Go Fast Elliptical Trainer 3000"
- let caloriesBurned: Double
- let minutes: Double
- }
-
- struct TreadmillWorkout: Exercise {
- let name: String = "Treadmill Workout"
- let caloriesBurned: Double
- let minutes: Double
- let laps: Double //跑步的圈数
- }
- extension TreadmillWorkout {
- var description: String {
- return "TreadmillWorkout(\(caloriesBurned) calories and \(laps) laps in \(minutes) minutes)"
- }
- }
-
- let ellipticalWorkout = EllipticalWorkout(caloriesBurned: 335, minutes: 30)
- let runningWorkout = TreadmillWorkout(caloriesBurned: 350, minutes: 25, laps: 10.5)
- //使用范型定义函数:计算每分钟消耗的卡路里
- func caloriesBurnedPerMinute<E: Exercise>(for exercise: E) -> Double {
- return exercise.caloriesBurned / exercise.minutes
- }
- print(caloriesBurnedPerMinute(for: ellipticalWorkout))
- print(caloriesBurnedPerMinute(for: runningWorkout))
-
- //拓展协议
- extension Exercise {
- //所有实现该协议的类型都可以使用通过拓展为该协议添加的属性和方法
- var caloriesBurnedPerMinute: Double {
- return caloriesBurned / minutes
- }
- }
-
- print(ellipticalWorkout.caloriesBurnedPerMinute)
- print(runningWorkout.caloriesBurnedPerMinute)
- print(ellipticalWorkout)
- print(runningWorkout)
-
- //带 where 子句的协议拓展
- extension Sequence where Iterator.Element == Exercise {
- func totalCaloriesBurned() -> Double {
- var total: Double = 0
- for exercise in self {
- total += exercise.caloriesBurned
- }
- return total
- }
- }
-
- let mondayWorkout: [Exercise] = [ellipticalWorkout, runningWorkout]
- print(mondayWorkout.totalCaloriesBurned())
-
-
- for exercise in mondayWorkout {
- print(exercise.title)
- }
- print(ellipticalWorkout.title)
- struct StackIterator<T>: IteratorProtocol {
- // typealias Element = T
-
- var stack: Stack<T>
-
- mutating func next() -> T? {
- return stack.pop()
- }
- }
-
- // Sequence 是实现 for-in 循环在内部使用的协议
- struct Stack<E>: Sequence {
- var items = [E]()
-
- // 使用 where 子句约束 Sequence 的元素类型
- mutating func pushAll<S: Sequence>(_ sequence: S) where S.Iterator.Element == E {
- for item in sequence {
- self.push(item)
- }
- }
-
- mutating func push(_ newItem: E) {
- items.append(newItem)
- }
-
- mutating func pop() -> E? {
- guard !items.isEmpty else {
- return nil
- }
- return items.removeLast()
- }
-
- func map<U>(_ f: (E) -> U) -> Stack<U> {
- var mappedItems = [U]()
- for item in items {
- mappedItems.append(f(item))
- }
- return Stack<U>(items: mappedItems)
- }
-
- func makeIterator() -> StackIterator<E> {
- return StackIterator(stack: self)
- }
- }
-
- var intStack = Stack<Int>()
- intStack.push(1)
- intStack.push(2)
- var doubledStack = intStack.map { 2 * $0 }
-
- print(intStack.pop())
- print(intStack.pop())
- print(intStack.pop())
- print(doubledStack.pop())
- print(doubledStack.pop())
-
- func myMap<T, U>(_ items: [T], _ f: (T) -> U) -> [U] {
- var result = [U]()
- for item in items {
- result.append(f(item))
- }
- return result
- }
- let strings = ["one", "two", "three"]
- //let stringLengths = myMap(strings, {(str: String) -> Int in
- // return str.count
- //})
- let stringLengths = myMap(strings) { $0.count }
- print(stringLengths)
-
- //类型约束
- func checkIfEqual<T: Equatable>(_ first: T, _ second: T) -> Bool {
- return first == second
- }
- print(checkIfEqual(1, 1))
- print(checkIfEqual("a string", "a string"))
- print(checkIfEqual("a string", "a different string"))
-
- //每个占位类型都可以有一个类型约束
- func checkIfDescriptionsMatch<T: CustomStringConvertible, U: CustomStringConvertible>(_ first: T, _ second: U) -> Bool {
- return first.description == second.description
- }
-
- print(checkIfDescriptionsMatch(Int(1), UInt(1)))
- print(checkIfDescriptionsMatch(1, 1.0))
- print(checkIfDescriptionsMatch(Float(1.0), Double(1.0)))
-
-
- var myStack = Stack<Int>()
- myStack.push(10)
- myStack.push(20)
- myStack.push(30)
- var myStackIterator = StackIterator(stack: myStack)
- while let value = myStackIterator.next() {
- print("got \(value)")
- }
-
- for value in myStack {
- print("for-in loop: got \(value)")
- }
- myStack.pushAll([1, 2, 3])
- for value in myStack {
- print("after pushing: got \(value)")
- }
- var myOtherStack = Stack<Int>()
- myOtherStack.pushAll([1, 2, 3])
- myStack.pushAll(myOtherStack)
- for value in myStack {
- print("after pushing item onto stack, got \(value)")
- }
- protocol TabularDataSource {
- var numberOfRows: Int { get }
- var numberOfColumns: Int { get }
- func label(forColumn column: Int) -> String
- func itemFor(row: Int, column: Int) -> String
- }
-
- protocol PrintableTabularDataSource: TabularDataSource, CustomStringConvertible {
- //
- }
-
- //组合协议,让 printTable 的参数符合 CustomStringConvertible 协议
- func printTable(_ dataSource: TabularDataSource & CustomStringConvertible) {
- print(dataSource)
- var firstRow = "|"
- var columnWidths = [Int]()
- for i in 0..<dataSource.numberOfColumns {
- let columnLabel = dataSource.label(forColumn: i)
- let columnHeader = " \(columnLabel) |"
- firstRow += columnHeader
- columnWidths.append(columnLabel.count)
- }
- print(firstRow)
-
- for i in 0..<dataSource.numberOfRows {
- var out = "|"
- for j in 0..<dataSource.numberOfColumns {
- let item = dataSource.itemFor(row: i, column: j)
- let paddingNeeded = columnWidths[j] - item.count
- let padding = repeatElement(" ", count: paddingNeeded).joined(separator: "")
- out += " \(padding)\(item) |"
- }
- print(out)
- }
- }
-
-
- struct Person {
- let name: String
- let age: Int
- let yearsOfExperience: Int
- }
-
- struct Department: TabularDataSource, CustomStringConvertible {
- let name: String
- var people = [Person]()
-
- var description: String {
- return "Department (\(name))"
- }
-
- init(name: String) {
- self.name = name
- }
-
- mutating func add(_ person: Person) {
- people.append(person)
- }
-
- var numberOfRows: Int {
- return people.count
- }
-
- var numberOfColumns: Int {
- return 3
- }
-
- func label(forColumn column: Int) -> String {
- switch column {
- case 0: return "Employee Name"
- case 1: return "Age"
- case 2: return "Years of Experience"
- default: fatalError("Invalid column!")
- }
- }
-
- func itemFor(row: Int, column: Int) -> String {
- let person = people[row]
- switch column {
- case 0: return person.name
- case 1: return String(person.age)
- case 2: return String(person.yearsOfExperience)
- default: fatalError("Invalid column!")
- }
- }
- }
-
- var department = Department(name: "Engineering")
- department.add(Person(name: "Joe", age: 30, yearsOfExperience: 6))
- department.add(Person(name: "Karen", age: 40, yearsOfExperience: 18))
- department.add(Person(name: "Fred", age: 50, yearsOfExperience: 20))
-
- printTable(department)
- import Cocoa
-
- extension String {
- /// 截取字符串
- /// - Parameter start: 起始索引(包含)
- /// - Parameter end: 结束索引(不包含)
- func substring(start: Int, end: Int) -> String {
- let firstIndex = index(startIndex, offsetBy: start)
- let lastIndex = index(startIndex, offsetBy: end)
- return String(self[firstIndex..<lastIndex])
- }
-
- /// 16进制字符串(可以有空格)转换成二进制数据
- func toData() -> Data {
- let hex = self.replacingOccurrences(of: " ", with: "")
- var arr = Array<UInt8>()
- for i in 0..<hex.count where i % 2 == 0 {
- let byteStr = hex.substring(start: i, end: i + 2)
- // print("byteStr = \(byteStr)")
- arr.append(UInt8(byteStr, radix: 16) ?? 0)
- }
- return Data(arr)
- }
- }
-
- extension Data {
-
- /// 按照 ASCII 转换成字符串
- func toAscii() -> String {
- return subdata2ascii(start: 0, end: self.count)
- }
-
- /// 转换成16进制字符串
- /// - Parameter withSpace: 可选参数,默认true,输出的字符串是否每两个字节之间放一个空格
- func toHex(withSpace: Bool = true) -> String {
- return subdata2hex(start: 0, end: self.count, withSpace: withSpace)
- }
-
- /// 将指定范围的数据转换成ASCII字符串
- /// - Parameter start: 起始索引(包含)
- /// - Parameter end: 结束索引(不包含)
- func subdata2ascii(start: Int, end: Int) -> String {
- if let str = String(data: self[start..<end], encoding: .ascii) {
- return str
- }
- return ""
- }
-
- /// 将指定范围的数据转换成16进制字符串
- /// - Parameter start: 起始索引(包含)
- /// - Parameter end: 结束索引(不包含)
- /// - Parameter withSpace: 可选参数,默认true,输出的字符串是否每两个字节之间放一个空格
- func subdata2hex(start: Int, end: Int, withSpace: Bool = true) -> String {
- let arr = Array<UInt8>(self[start..<end])
- let hex = arr.map({ byte -> String in
- return String(format: "%02X", byte)
- }).joined(separator: withSpace ? " " : "")
- return hex
- }
- }
-
-
- func test() {
- let hexString = "5A 58 48 0C 83 0E 47 07 22 2B 42 41 30 34 56 30 35"
- let data = hexString.toData()
- print("head = \(data.subdata2ascii(start: 0, end: 3))")
- print("mac = \(data.subdata2hex(start: 3, end: 9))")
- print("DeviceType = \(data.subdata2ascii(start: 9, end: 14))")
- print("version = \(data.subdata2ascii(start: 14, end: data.count))")
- print(data.toHex(withSpace: true))
- }
-
- test()
-
- let apples = 3
- let oranges = 5
- //只要与结束引号(""")的缩进匹配,就会删除每一行开始处的缩进
- let quotation = """
- Even though there's whitespace to the left,
- the actual lines aren't indented.
- Except for this line.
- Double quotes (") can appear without being escaped.
- I still have \(apples + oranges) pieces of fruit.
- """
- print(quotation)
- /** struct 类似 Kotlin 的 data class,等价写法是:
- data class Person(var firstName: String = "Matt", var lastName: String = "Mathias")
- */
- struct Person {
- var firstName = "Matt"
- var lastName = "Mathias"
- }
-
- var p = Person(firstName: "Jia", lastName: "Jiefei")
- print(p)
-
-
- //如果属性没有提供默认值,结构体会根据属性生成默认的成员初始化方法,并且直接打印结构体可以看到所有存储属性的值
- struct Device {
- var name: String
- var address: String
- // text 是计算属性,打印时不会输出
- var text: String {
- return "name=\(name), address=\(address)"
- }
- }
- print(Device(name: "Device", address: "11:22:33:44:55:66"))
-
- //而类就没有默认成员初始化方法了,需要自己编写初始化方法,并且直接打印类实例,不会输出各存储属性的值
- class BleDevice {
- var name: String
- var address: String
-
- required init(name: String, address: String) {
- self.name = name
- self.address = address
- }
- }
- print(BleDevice(name: "BleDevice", address: "AA:BB:CC:DD:EE:FF"))
- //类是引用类型
- class GreekGod {
- var name: String
-
- init(name: String) {
- self.name = name
- }
- }
-
- let hecate = GreekGod(name: "Hecate")
- let athena = GreekGod(name: "Athena")
- let zeus = GreekGod(name: "Zeus")
- let anotherHecate = hecate
- anotherHecate.name = "AnotherHecate"
- hecate.name //类是引用类型,改变 anotherHecate.name,hecate.name也会变
-
- //结构体是值类型
- struct Pantheon {
- var chiefGod: GreekGod
- }
-
- let pantheon = Pantheon(chiefGod: hecate)
-
- pantheon.chiefGod.name // AnotherHecate
- let greekPantheon = pantheon
- hecate.name = "Trivia"
- greekPantheon.chiefGod.name // Trivia
-
- let gods = [athena, hecate, zeus]
- let godsCopy = gods
- gods.last?.name = "Jupiter"
- godsCopy.last?.name // Jupiter
-
-
- //探究写时复制(copy on write, COW)
- fileprivate class IntArrayBuffer {
- var storage: [Int]
-
- init() {
- storage = []
- }
-
- init(buffer: IntArrayBuffer) {
- storage = buffer.storage
- }
- }
-
- struct IntArray {
- private var buffer: IntArrayBuffer
-
- init() {
- buffer = IntArrayBuffer()
- }
-
- func describe() {
- let str = buffer.storage.map { i in
- String(i)
- }.joined(separator: ", ")
- print("[\(str)]")
- // print(buffer.storage)
- }
-
- private mutating func copyIfNeeded() {
- //判断引用类型是否只有一个引用
- if !isKnownUniquelyReferenced(&buffer) {
- print("Making a copy of \(buffer.storage)")
- buffer = IntArrayBuffer(buffer: buffer)
- }
- }
-
-
- mutating func insert(_ value: Int, at index: Int) {
- copyIfNeeded()
- buffer.storage.insert(value, at: index)
- }
-
- mutating func append(_ value: Int) {
- copyIfNeeded()
- buffer.storage.append(value)
- }
-
- mutating func remove(at index: Int) {
- copyIfNeeded()
- buffer.storage.remove(at: index)
- }
- }
-
- var integers = IntArray()
- integers.append(1)
- integers.append(2)
- integers.append(4)
- integers.describe()
- var ints = integers
- ints.insert(3, at: 2)
- integers.describe()
- ints.describe()
虽然是讲继承,但代码中的注释也会涉及其他知识点!例子涉及3个.swift文件
Town.swift
- struct Town {
- let region: String
- var population: Int {
- didSet {
- print("The population has changed to \(population) from \(oldValue)")
- }
- }
- var numberOfStoplights: Int
-
- //自定义初始化方法,问号表示可失败的初始化方法
- init?(region: String, population: Int, stoplights: Int) {
- guard population > 0 else {
- return nil
- }
- self.region = region
- self.population = population
- numberOfStoplights = stoplights
- }
-
- //委托初始化
- init?(population: Int, stoplights: Int) {
- self.init(region: "N/A", population: population, stoplights: stoplights)
- }
-
- enum Size {
- case small
- case medium
- case large
- }
-
- //计算属性
- var townSize: Size {
- get {
- print("town size")//每次调用都会打印
- switch self.population {
- case 0...10_000:
- return Size.small
- case 10_001...100_000:
- return Size.medium
- default:
- return Size.large
- }
- }
- }
-
- //惰性存储属性,注意这里的等号以及结尾的圆括号
- lazy var name: String = {
- print("town name")//这里只会打印一次,即第一次访问该属性时
- return "XiShe"
- }()
-
-
- func printDescription() {
- print("Population: \(population), number of stoplights: \(numberOfStoplights), region: \(region)")
- }
-
- /* 如果结构体(确切的说,应该是值类型,结构体和枚举都是值类型)的一个实例方法需要修改结构体的属性,就必须使用 mutating 标记该方法 */
- mutating func changePopulation(by amount: Int) {
- population += amount
- }
-
- /* 对于值类型,类型方法使用static标记 */
- static func xxx() {
-
- }
- }
Monster.swift
- class Monster {
- // static 属性无法被子类覆盖
- static let isTerrifying = true
- // class 属性可被子类覆盖
- class var spookyNoise: String {
- return "Grrr"
- }
- var town: Town?
- var name: String
-
- var victimPool: Int {
- get {
- return town?.population ?? 0
- }
- set {
- town?.population = newValue
- }
- }
-
- //子类必须得实现的初始化方法
- required init(town: Town?, monsterName: String) {
- self.town = town
- name = monsterName
- }
-
-
- func terrorizeTown() {
- if town != nil {
- print("\(name) is terrorizing a town!")
- } else {
- print("\(name) hasn't found a town to terrorize yet...")
- }
- }
-
- /* 对于类,类型方法使用class或者static标记,区别在于static标记的方法无法被子类重写,也可以使用final class代替static */
- static func makeSpookyNoise() {
- print("Brains...")
- }
- }
Zombie.swift
- class Zombie: Monster {
- override class var spookyNoise: String {
- return "Brains..."
- }
- var walkWithLimp: Bool
- //只将 set 属性设置为私有,get 属性为默认的 internal
- private(set) var isFallingApart: Bool
-
- //指定初始化方法
- init(limp: Bool, fallingApart: Bool, town: Town?, monsterName: String) {
- walkWithLimp = limp
- isFallingApart = fallingApart
- //如果有父类,子类的指定初始化方法必须调用父类的指定初始化方法
- super.init(town: town, monsterName: monsterName)
- }
-
- //便捷初始化方法,必须调用指定初始化方法或者其他便捷初始化方法,但最终都要调用指定初始化方法,以确保所有属性都进行了初始化
- convenience init(limp: Bool, fallingApart: Bool) {
- self.init(limp: limp, fallingApart: fallingApart, town: nil, monsterName: "Fred")
- if walkWithLimp {
- print("This zombie has a bad knee.")
- }
- }
-
-
- required init(town: Town?, monsterName: String) {
- walkWithLimp = false
- isFallingApart = false
- super.init(town: town, monsterName: monsterName)
- }
-
- //实例被清除出内存时会触发反初始化
- deinit {
- print("Zombie named \(name) is no longer with use.")
- }
-
- //final 禁止子类重写该方法
- final override func terrorizeTown() {
- if !isFallingApart {
- town?.changePopulation(by: -10)
- }
- super.terrorizeTown()
- }
- }
测试代码
- var town = Town(region: "West", population: 10, stoplights: 6)
- town?.printDescription()
- for _ in 0..<3 {
- if let townSize = town?.townSize, let townName = town?.name {
- print(townSize)
- print(townName)
- }
- town?.changePopulation(by: 1_000_000)
- }
- //let genericMonster = Monster()
- //genericMonster.town = town
- //genericMonster.terrorizeTown()
- var fredTheZombie: Zombie? = Zombie(limp: false, fallingApart: false, town: town, monsterName: "Fred")
- //fredTheZombie.terrorizeTown()
- //fredTheZombie.town?.printDescription()
- //Monster.makeSpookyNoise()
- print("Victim pool: \(fredTheZombie?.victimPool)")
- fredTheZombie?.victimPool = 500
- fredTheZombie = nil
- print(Monster.spookyNoise)
- print(Zombie.spookyNoise)
- //初始化数组的3种方式,本人习惯上倾向使用第一种
- //使用 var 就是可变数组,let就是不可变数组
- var bucketList: Array<String> = []
- var bucketList2:[String] = ["haha"]
- var arr = [Int]()
- arr.append(1)
- arr.append(3)
- arr.append(2)
- //print("bucketList.count=\(bucketList.count) arr[0]=\(arr[0])")
- //数组排序
- let sortedArray = arr.sorted(by: {a, b in
- a < b
- })
- print(sortedArray)
- //注:只有Array
才有 joined 方法,如果元素类型不是 String,得先通过 map 方法转一次 - let joinedString = arr.map { i in
- String(i)
- }.joined(separator: ", ")
- print("[\(joinedString)]")
-
- //字典也有多种初始化方式,这里只列出其中一种
- //使用 var 就是可变字典,let就是不可变字典
- var dict: Dictionary<String, Int> = [:]
- dict["one"] = 1
- dict["two"] = 2
- dict["three"] = 3
- //遍历字典
- for (key, value) in dict {
- print("\(key) = \(value)")
- }
- dict.removeValue(forKey: "one")
- dict["two"] = nil //将值设置为nil来删除键值对
- print(dict)