Cowboy Tech

Swift面向对象基础(上)

面向对象的特点

  1. 面向对象编程的三大特征:封装,继承,和多态
  2. Swift可以定义枚举,结构体,和类三种面向对象的类型

Class - 继承/引用类型

  1. 内存里的对象可以有多个引用,即多个引用变量指向同一个对象
  2. 如果一个引用更改了,那对象里的值也会更改。
  3. “===” 这个等号只能用于引用类型的比较,不能用于值类型的比较,所以不能用于枚举或者结构体
  4. “==” or “!=” ,这两个也可以用于比较引用类型,但是要用到运算符重载,详情见后期课程

格式

必须有init method

class Movie {

    let title: String
    let director: String
    let releaseYear: Int

    init(title: String, director: String, releaseYear: Int) {
        self.title = title
        self.director = director
        self.releaseYear = releaseYear
    }
}

Property

三类property: Stored property, Type properties, Computed property

默认是internal,就是可以app内访问

1

Stored property

大多数的stored property 是定义为常量,必须在init的时候被设定,external name 在init method中是必须的

var thursdayNightMovie = Movie(title:"Point Break", director:"Kathryn Bigelow", releaseYear: 1991)

Type properties & Computed Properties

class KidsMovie {
    let title: String
    let director: String
    let releaseYear: Int
    var mpaaRating: String

    //Type property
    static let permittedRatings = ["G", "PG"]

    let reviewScores:[Double]

    var metaScore: Double {
        get {
            let value = reviewScores.reduce(0) { $0 + $1 } / Double(reviewScores.count)
            return value
        }
    }

    init(title: String, director: String, releaseYear: Int, mpaaRating:String, reviewScores: [Double]) {
        self.mpaaRating = mpaaRating
        self.title = title
        self.director = director
        self.releaseYear = releaseYear
        self.reviewScores = reviewScores
    }
}

Calling Type methods

UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary)

使用class func ,子类可以重载,使用static则不会

class Hello {

let pipi:String

init (hello:String){
    self.pipi = hello
}

//or class func .....
static func diao (hello:String){
print("why")
}
}

Enumeration - 不能继承/值类型

  1. 值对象是要复制的
  2. 每个值对象的更改,不会影响其他对象的更改
  3. 因此枚举和结构体是没有继承的

定义

Enum可以看做是一组有限的“抽象概念”的集合 (数组需要指定具体的数值类型)

enum PrimaryColor {
    case Red
    case Blue
    case Yellow
}

可以用一个case,然后其他用逗号隔开

enum Aunties {
    case Aime, Billie, Diane, Gail, Janie, Pam
}

enum中的元素可以设定任何类型原始值,如string,int

enum AmericanLeagueWest: String {
    case As = "Oakland"
    case Astros = "Houston"
    case Angels = "Los Angeles"
    case Mariners = "Seattle"
    case Rangers = "Arlington"    
}

var weather: AmericanLeagueWest
weather = AmericanLeagueWest.As
weather = .As //也可以这样写

使用rawValue提取成员的原始值

var message = "I hope the A's stay in \(AmericanLeagueWest.As.rawValue)"

Enums and switch

enum CaliforniaPark {
    case Yosemite, DeathValley, Lasson, Sequoia
}

var warning = ""
var destination = CaliforniaPark.Yosemite

例子 1:switch中的case如果没有覆盖枚举的所有值,必须添加default语句

switch destination {
    case .Yosemite:
        warning = "Beware of aggressive bears!"
    case .DeathValley:
        warning = "Beware of dehydration!"
    case .Lasson:
        warning = "Watch out for boiling pools!"
    case .Sequoia:
        warning = "Watch out for falling trees!"
}

例子 2:

// Below is an enum and an if-else statement for implementing the game Rock-Paper-Scissors.
enum roshamboMove {
    case Rock, Paper, Scissors
}

var myMove = roshamboMove.Scissors
var yourMove = roshamboMove.Scissors

var resultsMessage = ""

if myMove == .Rock && yourMove == .Paper || myMove == .Paper && yourMove == .Rock {
    resultsMessage = "Paper covers Rock."
} else if myMove == yourMove {
    resultsMessage = "It's a tie!"
} else if myMove == .Rock && yourMove == .Scissors || myMove == .Scissors && yourMove == .Rock {
    resultsMessage = "Rock crushes Scissors. "
} else if myMove == .Paper && yourMove == .Scissors || myMove == .Scissors && yourMove == .Paper {
    resultsMessage = "Scissors cut Paper."
} 

// Solution
switch (myMove, yourMove) {
case (.Rock, .Paper), (.Paper, .Rock):
    resultsMessage = "Paper covers Rock."
case (.Rock, .Rock), (.Paper, .Paper), (.Scissors, .Scissors):
    resultsMessage = "It's a tie!"
case (.Rock, .Scissors), (.Scissors, .Rock):
    resultsMessage = "Rock crushes Scissors."
case (.Paper, .Scissors), (.Scissors, .Paper):
    resultsMessage = "Scissors cut Paper."
}

// Alternate solution
switch (myMove, yourMove) {
case (.Rock, .Paper), (.Paper, .Rock):
    resultsMessage = "Paper covers Rock."
case let (a, b) where a==b :
    resultsMessage = "It's a tie!"
case (.Rock, .Scissors), (.Scissors, .Rock):
    resultsMessage = "Rock crushes Scissors."
case (.Paper, .Scissors), (.Scissors, .Paper):
    resultsMessage = "Scissors cut Paper."
default:
    resultsMessage = "Paper covers Rock."
}

例子3

var score = 97
var letterGrade = ""

// Solution
switch score {
case 90...100:
    letterGrade = "A"
case 80...89:
    letterGrade = "B"
case 70...79:
    letterGrade = "C"
case 60...69:
    letterGrade = "D"
default:
    letterGrade = "Incomplete"
}

整型的枚举

//可以自动推断,不用每个都赋予原始值
enum Weekday: Int{
  case Mon, Tur, Wen = 3, Thur, Fri, Sat , Sun
}

字符串枚举

//必须每个都赋予原始值,因为不能自动推断
enum Season3: Character{
  case Spring = "春"
  case Summer = "夏"
  case Fall = "秋"
  case Winter = "冬"
}

获取枚举值

var mySeason = Season3(rawValue:"春")
if mySeason != nil {
  switch(mySeason!){ //不为空才能进行强制解析
  case .Spring:
    print("春天不是读书天")
  case .Summer:
    print("夏天炎炎正好眠")
  case .Fall , .Winter:
    print("秋多蚊蝇冬日冷")
  default:
    print("读书只好等明年")

  }
}

关联值

enum Planet {
case Earth(weight: Double , name:String)
case Mars (density: Double, name: String, weight:Double)
case Venus(Double, String)
case Saturn
case Neptune
}

var p1 = Planet.Earth(weight:1.0, name:"地球")
var p2 = Planet.Venus(0.815,"金星")
var p3 = Planet.Mars(density:3.95, name:"火星",weight:0.1)

switch (p3){
//将关联值绑定到变量或者常量来提取
case Planet.Earth(var weight , var name):
   print("此行星的名字为:\(name),质量相当于\(weight)个地球")

//将关联值都提取为常量或者变量,只将一个var或者let放在枚举成员之前
case let Planet.Mars(density:d, name:n, weight:w):
   print("此行星的名字为:\(n),质量相当于\(w)个地球,密度为\(d)")
default:
   break
}

Struct - 不能继承/值类型

struct PictureFrame {
    var width = 5
    var height = 7
    var thickness: Double = 1.5

    var area: Int {
        get {
            return (width * height)/2
        }
    }
}

Struct自动生成init method

var familyReunionFrame = PictureFrame(width: 10, height: 8, thickness: 1.5)
familyReunionFrame.area

enum, class, or struct?

只是单纯的存储数据,不需要继承

 Struct Triangle {
    let angles = [30, 60, 90]
    let sides = [3,4,5]
}

存储“有限“的“成员”,不必考虑什么类型的数值

enum UIImagePickerControllerSourceType : Int {    
    case PhotoLibrary
    case Camera
    case SavedPhotosAlbum
}

只是单纯的存储数据,不需要继承

Struct Name {
    var firstName: String
    var lastName: String
}

存储“有限“的“成员”,不必考虑什么类型的数值

enum Subject {
    case Math
    case English
    case Spanish
    case Science
}

有各种类型的学生,大学,中学,意味着需要继承

class Student {
    var grades = [97.0, 99.0, 98.0]
    let name = Name(firstName:"Grace", lastName:"Hopper")
    var favoriteSubject = Subject.Science

    var gradePointAverage: Double {
        get {
            return (grades.reduce(0){$0 + $1})/Double (grades.count)
        }
    }
}