以下是第1章的学习笔记,全是copy,哈哈

import Foundation

// 打印helloworld
print("Hello, world")

// 使用 let来声明常量,使用 var来声明变量。一个常量的值,在编译的时候,并不需要有明确的值,但是你只能为它赋值一次。也就是说你可以用常量来表示这样一个值:你只需要决定一次,但是需要使用很多次。
var myVariable = 42
myVariable = 50
let myConstant = 42

// 如果初始值没有提供足够的信息(或者没有初始值),那你需要在变量后面声明类型,用冒号分割。
let implicitInteger =  70
let implicitDouble =  70.0
let explicitDouble:  Double = 70

// 练习:创建一个常量,显式指定类型为 Float并指定初始值为4。
let a001: Float =4

// 值永远不会被隐式转换为其他类型。如果你需要把一个值转换成其他类型,请显式转换。
let label = "The width is"
let width = 94
let widthLabel = label +String(width)

// 有一种更简单的把值转换成字符串的方法:把值写到括号中,并且在括号之前写一个反斜杠。例如:
let apples = 3
let oranges = 5
let appleSummary =  "I have \(apples) apples."
let fruitSummary =  "I have \(apples +oranges) pieces of fruit."
print(appleSummary)
print(fruitSummary)

// 练习:使用 \()来把一个浮点计算转换成字符串,并加上某人的名字,和他打个招呼。
let age = 5.4
print("Jack,\(age)")

// 使用方括号 []来创建数组和字典,并使用下标或者键(key)来访问元素。
var shoppingList = ["柴","米","油","盐","酱","醋","茶"];
shoppingList[1] ="水"

var person = [
    "age" :15,
    "name" :"吖吖"
]
person["age"] =17

// 要创建一个空数组或者字典,使用初始化语法。
let emptyArray = [String]()
let emptyDictionary = [String:Float]()

// 如果类型信息可以被推断出来,你可以用 []和 [:]来创建空数组和空字典——就像你声明变量或者给函数传参数的时候一样。
shoppingList = []
let occupations = [:]

// 使用 if和 switch来进行条件操作,使用 for-in、 for、 while和 repeat-while来进行循环。包裹条件和循环变量括号可以省略,但是语句体的大括号是必须的。
let individualScores = [75,43,103,87,12]
var teamScore = 0
for score inindividualScores {
    if (score >50) {
        teamScore +=3
    } else {
        teamScore +=1
    }
}
print(teamScore)
// 在 if语句中,条件必须是一个布尔表达式——这意味着像 if score { ... }这样的代码将报错,而不会隐形地与 0做对比。

var optionalString:String? ="Hello"
print(optionalString ==nil)

var optionalName: String? ="John Appleseed"
var greeting = "Hello!"
if let name =optionalName {
    greeting ="Hello,\(name)"
} else {
    greeting ="Hello, nil";
}
print(greeting)

// switch 支持任意类型的数据以及各种比较操作——不仅仅是整数以及测试相等。不能删除default语句,否则报错
// 运行 switch中匹配到的子句之后,程序会退出 switch语句,并不会继续向下运行,所以不需要在每个子句结尾写 break 。
let vegetable = "red pepper"
var vegetableComment =  ""
switch vegetable {
    case"celery":
        vegetableComment ="Add some raisins and make ants on a log."
    case"cucumber","watercress":
        vegetableComment ="That would make a good tea sandwich."
    caselet xwhere x.hasSuffix("pepper"):
        vegetableComment ="Is it a spicy\(x)?"
    default:
        vegetableComment ="Everything tastes good in soup."
}
print(vegetableComment);



//你可以使用 for-in来遍历字典,需要两个变量来表示每个键值对。字典是一个无序的集合,所以他们的键和值以任意顺序迭代结束。
let interestingNumbers = [
    "Prime": [2,3,5,7,11,13],
    "Fibonacci": [1,1,2,3,5,8],
    "Square": [1,4,9,16,25],
]
var largest = 0
for (kind, numbers)  in interestingNumbers {
    for numberin numbers {
        largest = number
    }
}
print(largest)

//使用 while来重复运行一段代码直到不满足条件。循环条件也可以在结尾,保证能至少循环一次。
var n = 2
while n <100 {
    n =n *2
}
print("n =\(n)")

var m = 2
repeat {
    m =m *2
} whilem <100
print("m =\(m)")

//你可以在循环中使用 ..<来表示范围,也可以使用传统的写法,两者是等价的:
//使用 ..<创建的范围不包含上界,如果想包含的话需要使用 ...。
var firstForLoop =  0;
for i in0..<4 {
    firstForLoop += i
}
print("firstForLoop = " +String(firstForLoop))

var secondForLoop =  0
for var i =0; i <4; ++i {
    secondForLoop += i
}
print("secondForLoop = " +String(secondForLoop))


//使用 func来声明一个函数,使用名字和参数来调用函数。使用 ->来指定函数返回值的类型。
func greet(name: String, day:String) ->String {
    return"Hello\(name), today is\(day)."
}
print(greet("Bob", day:"Tuesday"))

//练习:删除 day参数,添加一个参数来表示今天吃了什么午饭。
func greet(name: String, whatdinner:String) ->String {
    return"Hello\(name), today eat\(whatdinner)."
}
print(greet("Bob", whatdinner:"fish"))

func calculateStatistics(scores: [Int]) -> (min:Int, max:Int, sum:Int) {
    var min = scores[0]
    var max = scores[0]
    var sum =0
    for scorein scores {
        if score > max {
            max = score
        } elseif score < min {
            min = score
        }
        sum += score
    }
    return (min, max, sum)
}
let statistics = calculateStatistics([5,3,100,3,9])
print("statistics.sum is\(statistics.sum)")
print("statistics.0 is\(statistics.0)")


//函数可以带有可变个数的参数,这些参数在函数内表现为数组的形式:
func sumOf(numbers:  Int...) -> Int {
    var sum =0
    for numberin numbers {
        sum += number
    }
    return sum
}
sumOf()
sumOf(42,597,12)


//练习:写一个计算参数平均值的函数。
func avl(numbers: Int...) ->Int {
    var sum =0
    for numberin numbers {
        sum += number
    }
    return sum / numbers.count
}
print("平均值是:\(avl(5,9,10))")

//函数可以嵌套。被嵌套的函数可以访问外侧函数的变量,你可以使用嵌套函数来重构一个太长或者太复杂的函数。
func returnFifteen() ->  Int {
    var y =10
    func add() {
        y += 5
    }
    add()
    return y
}
returnFifteen()

//函数是第一等类型,这意味着函数可以作为另一个函数的返回值。
func makeIncrementer() -> (Int ->Int) {
    func addOne(number:Int) ->Int {
        return1 + number
    }
    returnaddOne
}
var increment = makeIncrementer()
increment(7)

//函数也可以当做参数传入另一个函数。
func hasAnyMatches(list: [Int], condition:Int ->Bool) ->Bool {
        for itemin list {
            if condition(item) {
                returntrue
            }
        }
        returnfalse
}
func lessThanTen(number:  Int) -> Bool {
        return number <10
}
var numbers = [20,19,7,12]
print(hasAnyMatches(numbers, condition:lessThanTen))


//使用 class和类名来创建一个类。类中属性的声明和常量、变量声明一样,唯一的区别就是它们的上下文是类。同样,方法和函数声明也一样。
class Shape {
    var numberOfSides =0
    func simpleDescription() ->String {
        return"A shape with\(numberOfSides) sides."
    }
    let number1 =5
    func getANum(number:Int) {
        print(number)
    }
}

//这个版本的 Shape类缺少了一些重要的东西:一个构造函数来初始化类实例。使用 init来创建一个构造器。
class NamedShape {
        var numberOfSides:Int =0
        var name:String
        
        init(name:String) {
            self.name = name
        }
        
        func simpleDescription() ->String {
            return"A shape with\(numberOfSides) sides."
        }
}


class Square: NamedShape {
            var sideLength:Double
            
            init(sideLength:Double, name:String) {
                self.sideLength = sideLength
                super.init(name: name)
                numberOfSides =4
            }
            
            func area() ->Double {
                returnsideLength *sideLength
            }
            
            overridefunc simpleDescription() ->String {
                return"A square with sides of length\(sideLength)."
            }
}
let test = Square(sideLength:5.2, name:"my test square")
test.area()
test.simpleDescription()


//练习:创建 NamedShape的另一个子类 Circle ,构造器接收两个参数,一个是半径一个是名称,在子类 Circle中实现 area() 和 simpleDescription()方法。
class Circle: NamedShape {
    var radius:Double
    
    init(radius:Double, name:String) {
        self.radius = radius
        super.init(name: name)
        numberOfSides =0
    }
    
    func area() ->Double {
        return3.14 *radius *radius
    }
    
    overridefunc simpleDescription() ->String {
        return"A circle with sides of radius\(radius)."
    }
}


//除了储存简单的属性之外,属性可以有 getter和 setter。
class EquilateralTriangle:NamedShape {
    var sideLength:Double =0.0
    
    init(sideLength:Double, name:String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides =3
    }
    var perimeter:Double {
        get {
            return3.0 *sideLength
        }
        set {
            sideLength = newValue /3.0
        }
    }
    overridefunc simpleDescription() ->String {
        return"An equilateral triagle with sides of length\(sideLength)."
    }
}
var triangle = EquilateralTriangle(sideLength:3.1, name:"a triangle")
print("triangle.perimeter is\(triangle.perimeter)")
triangle.perimeter =9.9
print("triangle.sideLength is\(triangle.sideLength)")


//注意 EquilateralTriangle类的构造器执行了三步:
//1. 设置子类声明的属性值
//2. 调用父类的构造器
//3. 改变父类定义的属性值。其他的工作比如调用方法、getters和setters也可以在这个阶段完成。



//使用 enum来创建一个枚举。就像类和其他所有命名类型一样,枚举可以包含方法。
enum Rank: Int {
    case Ace =1
    case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
    case Jack, Queen, King
            
    func simpleDescription() ->String {
        switchself {
            case .Ace:return"ace"
            case .Jack:return"jack"
            case .Queen:return"queen"
            case .King:return"king"
            default:returnString(self.rawValue)
        }
    }
}
let ace = Rank.Ace
let aceRawValue = ace.rawValue

//枚举的成员值是实际值,并不是原始值的另一种表达方法。实际上,以防原始值没有意义,你不需要设置。
enum Suit {
            case Spades, Hearts, Diamonds, Clubs
            func simpleDescription() ->String {
                switchself {
                    case .Spades:return"spades"
                    case .Hearts:return"hearts"
                    case .Diamonds:return"diamonds"
                    case .Clubs:return"clubs"
                }
            }
}
let hearts = Suit.Hearts
let heartsDescription =  hearts.simpleDescription()

//使用 struct来创建一个结构体。结构体和类有很多相同的地方,比如方法和构造器。它们之间最大的一个区别就是结构体是传值,类是传引用。
struct Card {
    var rank:Rank
    var suit:Suit
    func simpleDescription() ->String {
        return"The\(rank.simpleDescription()) of\(suit.simpleDescription())"
    }
}
let threeOfSpades =  Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription =threeOfSpades.simpleDescription()


//使用 protocol来声明一个协议。
protocol ExampleProtocol {
    var simpleDescription:String {get }
    mutatingfunc adjust()
}
//类、枚举和结构体都可以实现协议。
class SimpleClass:  ExampleProtocol {
                var simpleDescription:String ="A very simple class."
                var anotherProperty:Int =69105
                func adjust() {
                    simpleDescription +=" Now 100% adjusted."
                }
}
var a = SimpleClass()
a.adjust()
let aDescription =  a.simpleDescription
print("aDescription is\(aDescription)")

struct SimpleStructure:  ExampleProtocol {
                var simpleDescription:String ="A simple structure"
                mutatingfunc adjust() {
                    simpleDescription +=" (adjusted)"
                }
}
var b = SimpleStructure()
b.adjust()
let bDescription =  b.simpleDescription
print("bDescription is\(bDescription)")

//练习:写一个实现这个协议的枚举。