第二部分 枚举 ~ 构造过程

import UIKit

var greeting = "Hello, playground"
// 枚举 今日的目标  1枚举 .2类和结构体 , 3属性 , 4方法 , 5下标 ,6继承 7构造过程

//枚举成员的遍历
//在一些情况下,你会需要得到一个包含枚举所有成员的集合。可以通过如下代码实现:
//令枚举遵循 CaseIterable 协议。Swift 会生成一个 allCases 属性,用于表示一个包含枚举所有成员的集合。下面是一个例子:
enum Beverage: CaseIterable {
    case cofffe, tea, juice
}
let numbersOfChoice = Beverage.allCases.count
print("1")

for beverage in Beverage.allCases {
    print(beverage)
}


enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

var productBarcode = Barcode.upc(8, 85909, 51226, 3)

//productBarcode = Barcode.qrCode("ADDFFffgg")

switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
    print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case .qrCode(let productCode):
    print("QR code: \(productCode)")
}

switch productBarcode {
case let .upc(numberSystem,  manufacturer, product, check):
    print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case let .qrCode(productCode):
    print("QR code: \(productCode)")
}

// 原始值
enum ASCIIControlCharacter: Character {
case tab = "\t"
case lineFeed = "\n"
case carriageReturn = "\r"
}
//原始值可以是字符串、字符,或者任意整型值或浮点型值。每个原始值在枚举声明中必须是唯一的。


// 原始值的隐式赋值

enum Planet: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}

enum CompassPoint: String {
    case north, south , east, west
}

let earthOrder = Planet.earth.rawValue

let sunsetDirection = CompassPoint.west.rawValue
//这个例子利用原始值 7 创建了枚举成员 Uranus:
let possiblePanet = Planet(rawValue: 7)
// possiblePlanet 类型为 Planet? 值为 Planet.uranus

let positionToFind = 11
//这个例子使用了可选绑定(optional binding),试图通过原始值 11 来访问一个行星。if let somePlanet = Planet(rawValue: 11) 语句创建了一个可选 Planet,如果可选 Planet 的值存在,就会赋值给 somePlanet。在这个例子中,无法检索到位置为 11 的行星,所以 else 分支被执行。
if let someplanet = Planet(rawValue: positionToFind) {
    switch someplanet {
    case .earth:
        print("Mostly harmless")
    default:
        print("Not a safe place for humans")
    }
} else {
    print("Ther is not a  panet at positon \(positionToFind)")
}

// 递归枚举
//递归枚举是一种枚举类型,它有一个或多个枚举成员使用该枚举类型的实例作为关联值。使用递归枚举时,编译器会插入一个间接层。你可以在枚举成员前加上 indirect 来表示该成员可递归。
enum ArithmeticExpression {
    case number(Int)
    indirect case addition(ArithmeticExpression,ArithmeticExpression)
    indirect case multiplication(ArithmeticExpression,ArithmeticExpression)
}


let five  = ArithmeticExpression.number(5)
let four  = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))

func evaluate(_ expression: ArithmeticExpression) -> Int {
    switch expression {
    case let .number(value):
        return value
    case let .addition(left, right):
        return evaluate(left) + evaluate(right)
    case let .multiplication(left, right):
        return evaluate(left) * evaluate(right)
    }
}

print(evaluate(product))


// 类和结构体
struct Resolution {
    var wight = 0
    var height = 0
}

class VideoMode {
    var resolution = Resolution()
    var interlaced = false
    var frameRate = 0.0
    var name: String?
}

let someResolution = Resolution()
let someVideoMode = VideoMode()

print("wi is \(someResolution.wight)")

someVideoMode.resolution.wight = 1280
print("wi is \(someVideoMode.resolution.wight)")

let vga = Resolution(wight: 640, height: 480)

let hd = Resolution(wight: 1920, height: 1080)
var cinama = hd

cinama.wight = 2048

print("cinema is now  \(cinama.wight) pixels wide")

print("cinema is now  \(hd.wight) pixels wide")

enum CompassPoint2 {
    case north, south, east, west
    mutating func turnNorth() {
        self = .north
    }
}

var currentDirection = CompassPoint2.west

let rememberedDirection = currentDirection

//当 rememberedDirection 被赋予了 currentDirection 的值,实际上它被赋予的是值的一个拷贝。赋值过程结束后再修改 currentDirection 的值并不影响 rememberedDirection 所储存的原始值的拷贝
currentDirection.turnNorth()
print("The current direction is \(currentDirection)")
print("The remembered direction is \(rememberedDirection)")



//类是引用类型
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080!"
tenEighty.frameRate = 25.0

let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0

print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")

//恒等运算符

if tenEighty === alsoTenEighty {
    print("tenEighty and alsoTenEighty refer to the same VideoMode instance.")
}

//请注意,“相同”(用三个等号表示,===)与“等于”(用两个等号表示,==)的不同。“相同”表示两个类类型(class type)的常量或者变量引用同一个类实例。“等于”表示两个实例的值“相等”或“等价”,判定时要遵照设计者定义的评判标准。


//属性

//属性将值与特定的类、结构体或枚举关联。存储属性会将常量和变量存储为实例的一部分,而计算属性则是直接计算(而不是存储)值。计算属性可以用于类、结构体和枚举,而存储属性只能用于类和结构体。


//存储属性

struct FixedLengthRange {
    var firstValue: Int
    let length: Int
}

var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
rangeOfThreeItems.firstValue = 6

let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
//如果创建了一个结构体实例并将其赋值给一个常量,则无法修改该实例的任何属性,即使被声明为可变属性也不行:
//rangeOfFourItems.firstValue = 6 //报错的 ❌

//这种行为是由于结构体属于值类型。当值类型的实例被声明为常量的时候,它的所有属性也就成了常量。
//属于引用类型的类则不一样。把一个引用类型的实例赋给一个常量后,依然可以修改该实例的可变属性。

class DataImporter {
    var fileName = "data.text"
}

class DataManager {
    lazy var importer = DataImporter()
    var data: [String] = []
}

let manager = DataManager()
manager.data.append("some data")
manager.data.append("Some more data")

print(manager.importer.fileName)

//计算属性
struct Point {
    var x = 0.0, y = 0.0
}

struct Size {
    var width = 0.0, height = 0.0
}

struct Rect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        
        set(newCenter) {
            origin.x = newCenter.x - (size.width / 2)
            origin.y = newCenter.y - (size.height / 2)
        }
    }
}

var square = Rect(origin: Point(x: 0, y: 0), size: Size(width: 10, height: 10))
let initialSquareCenter = square.center
square.center = Point(x: 15, y: 15)

print("square.origin is now at (\(square.origin.x), \(square.origin.y))")


// 只读计算属性
//只有 getter 没有 setter 的计算属性叫只读计算属性。只读计算属性总是返回一个值,可以通过点运算符访问,但不能设置新的值。

struct Cubiod {
    var width = 0.0 , height = 0.0, depth = 0.0
    var volume: Double {
        return width * height * depth
    }
}

let fourByFiveByTwo = Cubiod(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")



///属性观察器

class StepCounter {
    var totalSteps: Int = 0 {
        willSet(newTotalSteps) {
            print("将 totalSteps 的值设置为 \(newTotalSteps)")
        }
        didSet {
            if totalSteps > oldValue {
                print("增加了 \(totalSteps - oldValue) 步")//didSet 没有为旧值提供自定义名称,所以默认值 oldValue 表示旧值的参数名。
            }
        }
    
    }
}


let stepCounter = StepCounter()
stepCounter.totalSteps = 200
stepCounter.totalSteps = 360
stepCounter.totalSteps = 896

@propertyWrapper
struct TwelveOrLess {
    private var number = 0
    var wrappedValue: Int {
        get {return number}
        set {number = min(newValue,12)}
    }
}


struct SmallRectangle {
    @TwelveOrLess var height:Int
    @TwelveOrLess var width:Int
}

var rectangle = SmallRectangle2()

print(rectangle.height)

rectangle.height = 24

print(rectangle.height)


struct SmallRectangle2 {
    private var _height = TwelveOrLess()
    private var _width = TwelveOrLess()
    var height: Int {
        get {return _height.wrappedValue}
        set {_height.wrappedValue = newValue}
    }
    
    var width: Int {
        get { return _width.wrappedValue }
        set { _width.wrappedValue = newValue }
    }
}



@propertyWrapper
struct SmallNumber2 {
    private var maxium: Int
    private var number: Int
    
    var wrappedValue: Int {
        get { return number }
        set { number = min(newValue, maxium)}
    }
    
    init(){
        maxium = 12
        number = 0
    }
    
    init(wrappedValue: Int) {
        maxium = 12
        number = min(wrappedValue, maxium)
    }
    
    init(wrappedValue: Int, maximum: Int) {
        self.maxium = maximum
        number = min(wrappedValue, maximum)
    }
    
}


struct ZeroRectangle {
    @SmallNumber2 var height: Int
    @SmallNumber2 var width: Int
}

var zeroRectangle = ZeroRectangle()

print(zeroRectangle.height, zeroRectangle.width)



struct UnitRectangle {
    @SmallNumber2 var height: Int = 1
    @SmallNumber2 var width: Int = 1
}

var unitRectangle = UnitRectangle()
print(unitRectangle.height, unitRectangle.width)


struct NarrowRectangle {
    @SmallNumber2(wrappedValue: 2, maximum: 5) var height: Int
    @SmallNumber2(wrappedValue: 3, maximum: 4) var width: Int
}

var narrowRectangle = NarrowRectangle()
print(narrowRectangle.height, narrowRectangle.width)

narrowRectangle.height = 100
narrowRectangle.width = 100
print(narrowRectangle.height, narrowRectangle.width)


struct MixedRectangle {
    @SmallNumber2 var height: Int = 1
    @SmallNumber2( maximum: 9) var width: Int = 2
}


var mixedRectangle = MixedRectangle()
print(mixedRectangle.height)
// 打印 "1"

mixedRectangle.height = 20
print(mixedRectangle.height)
// 打印 "12"
//全局变量和局部变量


//func someFunction() {
//    @SmallNumber2 var myNumber: Int = 0
//
//    myNumber = 10
//
//}


struct SomeStructure {
    static var storedTypeProperty = "Some value"
    static var computedTypeProperty: Int {
        return 1
    }
}

enum SomeEnumeration {
    static var storedTypeProperty = "Some value"
    static var computedTypeProperty: Int {
        return 6
    }
}

class SomeClass {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 27
    }
    class var overrideableComputedTypeProperty: Int {
        return 107
    }
}
print(SomeStructure.storedTypeProperty)
SomeStructure.storedTypeProperty = "Another value."
print(SomeStructure.storedTypeProperty)
print(SomeEnumeration.computedTypeProperty)
print(SomeClass.computedTypeProperty)



struct AudioChannel {
    static let thresholdLevel = 10
    static var maxInputLevelForAllChannels = 0
    var currentLevel: Int = 0 {
        didSet{
            if currentLevel > AudioChannel.thresholdLevel {
                currentLevel = AudioChannel.thresholdLevel
            }
            
            if currentLevel > AudioChannel.maxInputLevelForAllChannels {
                AudioChannel.maxInputLevelForAllChannels = currentLevel
            }
        }
    }
}


var leftChannel = AudioChannel()
var rightChannel = AudioChannel()

leftChannel.currentLevel = 7
print(leftChannel.currentLevel)
print(AudioChannel.maxInputLevelForAllChannels)

rightChannel.currentLevel = 11
print(rightChannel.currentLevel)

// 方法
class Counter {
    var count = 0
    func increment() {
        count += 1
    }
    
    func increment(by amount:Int) {
        count += amount
    }
    
    func reset() {
        count = 0
    }
}

let counter = Counter()
counter.increment()

counter.increment(by: 5)
counter.reset()


//func increment() {
//    self.count += 1
//}

struct Point2 {
    var x = 0.0, y = 0.0
    func isToTheRightOf(x: Double) -> Bool {
        return self.x > x
    }
}

let somePoint = Point2(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")
}


struct Point3 {
    var x = 0.0, y = 0.0
    mutating func moveBy(x deltaX: Double ,y deltaY: Double) {
        x += deltaX
        y += deltaY
    }
}

var somePoint2 = Point3(x: 1.0 , y: 1.0)

somePoint2.moveBy(x: 2.0, y: 3.0)
print("The point is now at (\(somePoint2.x), \(somePoint2.y))")

let fixedPoint = Point3(x: 3.0, y: 3.0)
//fixedPoint.moveBy(x: 2.0, y: 3.0)//注意,不能在结构体类型的常量(a constant of structure type)上调用可变方法,因为其属性不能被改变,即使属性是变量属性,详情参见 常量结构体的存储属性:



struct Point4 {
    var x = 0.0 , y = 0.0
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        self = Point4(x: x + deltaX, y: y + deltaY)
    }
}

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()
ovenLight.next()

class SomeClass2 {
    class func someTypeMethod() {
        // 在这里实现类型方法
    }
}
SomeClass2.someTypeMethod()
//类型方法和实例方法一样用点语法调用。但是,你是在类型上调用这个方法,而不是在实例上调用。下面是如何在 SomeClass 类上调用类型方法的例子:



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
    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)")
// 打印“highest unlocked level is now 2”


//  下标
//subscript(index: Int) -> Int {
//    get {
//
//    }
//
//    set(newValue) {
//
//    }
//}

struct TimesTable {
    let multiplier: Int
    subscript(index: Int) -> Int {
        return multiplier * index
    }
    
}

let threeTimesTable = TimesTable(multiplier: 3)

print("six times three is \(threeTimesTable[6])")

struct Matric {
    let rows: Int, columns: Int
    var grid: [Double]
    init(rows: Int, columns: Int) {
        self.rows = rows
        self.columns = columns
        grid = Array(repeating: 0.0, count: rows * columns)
    }
    
    func indexIsValid(row: Int, column: Int) -> Bool {
        return row >= 0 && row < rows && column >= 0 && column < columns
    }
    
    subscript(row: Int, column:Int) -> Double {
        get {
            assert(indexIsValid(row: row, column: column), "Index out of range")
            return grid[(row * columns) + column]
        }
        
        set {
            assert(indexIsValid(row: row, column: column), "Index out of range")
            grid[(row * columns) + column] = newValue
        }
    }
}


var matrix = Matric(rows: 2, columns: 2)
matrix[0, 1] = 1.5

matrix[1, 0] = 3.2
print("matrix = \(matrix)")


enum Planet2: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
    static subscript(n: Int) -> Planet2 {
        return Planet2(rawValue: n)!
    }
}
let mars = Planet2[4]
print(mars)

// 继承
//一个类可以继承另一个类的方法,属性和其它特性。当一个类继承其它类时,继承类叫子类,被继承类叫超类(或父类)。在 Swift 中,继承是区分「类」与其它类型的一个基本特征。




class Vehicle {
    var currentSpeed = 0.0
    var description: String {
        return "traveling at \(currentSpeed) miles per hour"
    }
    func makeNoise() {
        // 什么也不做——因为车辆不一定会有噪音
    }
}

let someVehicle = Vehicle()

print("Vehicle: \(someVehicle.description)")


//class SomeClass: SomeSuperclass {
//
//}

class Bicycle: Vehicle {
    var hasBasket = false
}

let bicycle = Bicycle()
bicycle.hasBasket = true
bicycle.currentSpeed = 15.0

print("Bicycle: \(bicycle.description)")
//新的 Bicycle 类自动继承 Vehicle 类的所有特性,比如 currentSpeed 和 description 属性,还有 makeNoise() 方法。

class Tandem: Bicycle {
    var currentNumberOfPassengers = 0
}

//如果你创建了一个 Tandem 的实例,你可以使用它所有的新属性和继承的属性,还能查询从 Vehicle 继承来的只读属性 description:
let tandem = Tandem()
tandem.hasBasket = true
tandem.currentNumberOfPassengers = 2
tandem.currentSpeed = 22.0
print("Tandem: \(tandem.description)")
// 打印:“Tandem: traveling at 22.0 miles per hour”


class Train: Vehicle {
    override func makeNoise() { // 关键字会提醒 Swift 编译器去检查该
        print("Choo Choo")
    }
}

// 构造过程

struct Fahrenheit {
    var temperature: Double
    init() {
        temperature = 20.0
    }
}
var f = Fahrenheit()

print("The default temperature is \(f.temperature)° Fahrenheit")

//你可以通过在属性声明时为 temperature 提供默认值来使用更简单的方式定义结构体 Fahrenheit :

//struct Fahrenheit {
//    var temperature = 32.0
//}


struct Celsius {
    var temperatureInCelsius: Double
    init (fromFahrenheit fahrenheit: Double) {
        temperatureInCelsius = (fahrenheit - 32.0) / 1.8
    }
    
    init(fromKelvin kelvin: Double) {
        temperatureInCelsius = kelvin - 273.15
    }
}

let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
let freezingPointOfWater = Celsius(fromKelvin: 273.15)


struct Color {
    let red, green , blue:  Double
    init(red: Double, green: Double , blue: Double) {
        self.red = red
        self.green = green
        self.blue = blue
    }
    
    init(white: Double) {
        red = white
        green = white
        blue = white
    }
}

let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)

let halfGray = Color(white: 0.5)


//let veryGreen = Color(0.0, 1.0, 0.0)
struct Celsius2 {
    var temperatureInCelsius: Double
    init(fromFahrenheit fahrenheit: Double) {
        temperatureInCelsius = (fahrenheit - 32.0) / 1.8
    }
    
    init(fromKelvin kelvin: Double) {
        temperatureInCelsius = kelvin - 273.15
    }
    
    init(_ celsius: Double){
        temperatureInCelsius = celsius
    }
}
let bodyTemperature = Celsius2(37.0)




class SurveyQuestion {
    var text: String
    
    var response: String?
    
    init(text: String) {
        self.text = text
    }
    
    func ask() {
        print(text)
    }
}

let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")
cheeseQuestion.ask()
cheeseQuestion.response = "Yes, I do like cheese."


//构造过程中常量属性的赋值
 


class ShoppingListItem1 {
    var name: String?
    var quatity = 1
    var purchased = false
}

var item = ShoppingListItem1()

struct Size2 {
    var width = 0.0 , height = 0.0
}
let twoByTwo = Size(width: 2, height: 2)

let twoByTwo2 = Size(width: 3)

let zeroByZero = Size()
print(zeroByZero.width, zeroByZero.height)

struct Size22 {
    var width = 0.0, height = 0.0
}

struct Point22 {
    var x = 0.0, y = 0.0
}


class VehicleNew {
    var numberOfWheels = 0
    var description: String {
        return "\(numberOfWheels) wheel(s)"
    }
}

let vehicle = VehicleNew()
print("Vehicle: \(vehicle.description)")
// Vehicle: 0 wheel(s)

class Bicycle22: VehicleNew {
    override init() {
        super.init()
        numberOfWheels = 2
    }
}


let bicycle22 = Bicycle22()
print("Bicycle: \(bicycle22.description)")
// 打印“Bicycle: 2 wheel(s)”

class Hoverboard: VehicleNew {
    var color: String
    init(color: String) {
        self.color = color
        // super.init() 在这里被隐式调用
    }
    override var description: String {
        return "\(super.description) in a beautiful \(color)"
    }
}


let hoverboard = Hoverboard(color: "silver")
print("Hoverboard: \(hoverboard.description)")
// Hoverboard: 0 wheel(s) in a beautiful silver


class Food {
    var name: String
    init(name: String) {
        self.name = name
    }

    convenience init() {
        self.init(name: "[Unnamed]")
    }
}

let nameMeat = Food(name: "Bacon")


let mysteryMeat = Food()

class RecipeIngredient: Food {
    var quantity: Int
    init(name: String, quantity: Int) {
        self.quantity = quantity
        super.init(name: name)
    }
    
    override convenience init(name: String) {
        self.init(name: name , quantity: 1)
    }
}

let oneMysteryItem = RecipeIngredient()
let oneBacon = RecipeIngredient(name: "Bacon")
let sixEggs = RecipeIngredient(name: "Eggs", quantity: 6)


class ShoppingListItem: RecipeIngredient {
    var purchased = false
    var description: String {
        var output = "\(quantity) X \(name)"
        output += purchased ? " ✔" : " ✘"
        return output
    }
}


var breakfastList = [
   ShoppingListItem(),
   ShoppingListItem(name: "Bacon"),
   ShoppingListItem(name: "Eggs", quantity: 6)
]

breakfastList[0].name = "Orange juice"
breakfastList[0].purchased = true

for item in breakfastList {
    print(item.description)
}

//可失败构造器

let wholeNumber: Double = 12345.0
let pi = 3.14159
if let valueMaintained = Int(exactly: wholeNumber) {
    print("\(wholeNumber) conversion to Int maintains value of \(valueMaintained)")
}


let valueChanged = Int(exactly: pi)

if valueChanged == nil {
    print("\(pi) conversion to Int does not maintain value")
}


struct Animal {
    let species: String
    init?(species: String) { // 可失败的构造器
        if species.isEmpty {
            return nil
        }
        self.species = species
    }
}

let someCreature = Animal(species: "Giraffe")

if let giraffe = someCreature {
    print("An animal was initialized with a species of \(giraffe.species)")
}

let anonymousCreature = Animal(species: "")

if anonymousCreature == nil {
    print("The anonymous creature could not be initialized")
}


//检查空字符串的值(如 "",而不是 "Giraffe" )和检查值为 nil 的可选类型的字符串是两个完全不同的概念。上例中的空字符串("")其实是一个有效的,非可选类型的字符串。这里我们之所以让 Animal 的可失败构造器构造失败,只是因为对于 Animal 这个类的 species 属性来说,它更适合有一个具体的值,而不是空字符串。



enum TemperatureUnit {
    case Kelvin, Celsius, Fahrenheit
    init?(symbol: Character) {
        switch symbol{
        case "K":
            self = .Kelvin
        case "C":
            self = .Celsius
        case "F":
            self = .Fahrenheit
        default:
            return nil
        }
    }
}

//你可以利用该可失败构造器在三个枚举成员中选择合适的枚举成员,当形参不能和任何枚举成员相匹配时,则构造失败:
let fahrenheitUnit = TemperatureUnit(symbol: "F")
if fahrenheitUnit != nil {
    print("This is a defined temperature unit, so initialization succeeded.")
}

let unknowUnit = TemperatureUnit(symbol: "X")
if unknowUnit == nil {
    print("This is not a defined temperature unit, so initialization failed.")

}


class Product2 {
    let name: String
    init?(name: String) {
        if name.isEmpty { return nil }
        self.name = name
    }
    
}

class CarItem: Product2 {
    let quantity: Int
    init?(name: String, quantity: Int) {
        if quantity < 1 { return nil }
        self.quantity = quantity
        super.init(name: name)
    }
}

if let twoSocks = CarItem(name: "sock", quantity: 2) {
    print("Item: \(twoSocks.name), quantity: \(twoSocks.quantity)")
}
//同样地,如果你尝试传入一个值为空字符串的 name 来创建一个 CartItem 实例,那么将导致父类 Product 的构造过程失败:

if let zeroShirts = CarItem(name: "shirt", quantity: 0) {
    print("Item: \(zeroShirts.name), quantity: \(zeroShirts.quantity)")
} else {
    print("Unable to initialize zero shirts")
}


//重写一个可失败构造器

class Document {
    var name: String?
    init() { }
    init?(name: String) {
        if name.isEmpty { return nil }
        self.name = name
    }
}


class AutomaticallyNamedDocument: Document {
    override init() {
        super.init()
        self.name = "[Untitled]"
    }
    
    //因为子类用另一种方式处理了空字符串的情况,所以不再需要一个可失败构造器,因此子类用一个不可失败构造器代替了父类的可失败构造器。
    override init(name: String) {
        super.init()
        if name.isEmpty {
            self.name = "[Untitled]"
        } else {
            self.name = name
        }
    }
}
//通常来说我们通过在 init 关键字后添加问号的方式(init?)来定义一个可失败构造器,但你也可以通过在 init 后面添加感叹号的方式来定义一个可失败构造器(init!),该可失败构造器将会构建一个对应类型的隐式解包可选类型的对象。
//你可以在 init? 中代理到 init!,反之亦然。你也可以用 init? 重写 init!,反之亦然。你还可以用 init 代理到 init!,不过,一旦 init! 构造失败,则会触发一个断言。

class UntitledDocument: Document {
    override init() {
        super.init(name: "[Untitled]")!
    }
}

//必要构造器
class SomeClass22 {
    required init() {
        
    }
}

class someSubClass: SomeClass22 {
    required init() {
        
    }
}

struct ChessBoard {
    let boradColors: [Bool] = {
        var temporaryBoard: [Bool] = []
        var isBlack = false
        for i in 1...8 {
            for j in 1...8 {
                temporaryBoard.append(isBlack)
                isBlack = !isBlack
            }
        }
        return temporaryBoard
    }()
    
    func squareIsBlackAt(row: Int, column:Int) -> Bool {
        return boradColors[(row * 8) + column]
    }
}

let board = ChessBoard()
print(board.squareIsBlackAt(row: 0, column: 1))
print(board.squareIsBlackAt(row: 3, column: 0))

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容