Swift笔记 3.0

初探类与对象
类,函数,闭包,枚举,结构体



3.1 类定义

类定义
实例化

import Foundation

// 4 类与对象

// 定义 类
 class Shape {
 	var numberOfSides = 0 //成员变量 (属性)
	 func desicriotion(){  //成员函数 (方法)
		 print("A shape with \(numberOfSides) sides.")
	 }
 }

 // 创建类对象,使用
 var s = Shape()
 s.numberOfSides = 6
 s.desicriotion()

psswift中 类 和 结构体 的区别

结构体不能被继承,类可以
他们都能拥有方法

结构体 ---- 值类型
类 ---- 引用类型

//swift中 类 和 结构体 的区别

struct S{
var data : Int = 1
}
var s1 = S()    //结构体对象
var s2 = s1     //调用拷贝构造函数对象s2
s2.data = 2
print("\(s1.data),\(s2.data)")
//输出 1,2


class C{
var data :Int = 1
}
var c1 = C() //类对象
var c2 = c1  //不调用拷贝构造函数,增加引用计数
c2.data = 2
print("\(c1.data),\(c2.data)")
//输出 2,2

3.2 类的 初始化器

入c++,java中的构造函数 或是 构造方法

初始化器 init 来构造 类对象
初始化器没有返回值
不自定义,会有一个默认初始化器械;若定义了一个就不会有;
反初始化器 (析构函数)deinit 有自带资源回收机制,一般不考虑析构;
ps: 【可选 符号】意思是,初始化可以失败, 则表示一定会成功

//初始化器  init 来构造 类对象

//命名的类
class NamedShape {
  var numberOfSides = 0
   var name :String

   init(name:String){       //构造函数
  	self.name = name
   }
   deinit {                 //析构函数 绝大情况不需要自己去写
  	print("Class NamedShape destructed")
   }

  func  simpleDescription() -> String {
  	return "\(name)'s shape with \(numberOfSides) sides"
   }
}

var shapeUnknow = NamedShape(name:"A")
shapeUnknow.numberOfSides = 4
print(shapeUnknow.simpleDescription())
shapeUnknow = NamedShape(name :"new")

3.3 类的属性

swift中,类有两种属性

存储属性:又由其为常量或变量(var / let)可分 常量存储属性 和 变量存储属性,作为实例的一部分,即为普通的属性,不赘述

计算属性: 它计算一个值,类似于方法的功能,提供了一个处理数据的入口与出口。其实它更像一个方法,通过一些存储属性值的使用,计算出来,但当用户调用时又感觉不到他是方法,使用起来和普通属性没有区别,即对用户透明。
另外: 有 getter stter 需要注意 。

 //举例: 等边三角形 ,属性周长计算属性
 class EquilaterTriangle{
 	var sideLen :Double   //边长
 	init (sideLen : Double){
 		self.sideLen = sideLen
	 }

 //计算属性 ,对象并没有为计算属性设置空间,需要时,会用其他属性计算,但对用户隐藏了使用如同正常属性
	 var perimeter: Double { //计算属性 边长
		 get { //读
			 return 3.0 * sideLen
 		}
		 set{ //写
			 sideLen = newValue/3.0
			 //跟新 sideLen。 newValue是set的参数
		 }
	 }
 }

 var et = EquilaterTriangle(sideLen: 3.1)
 print("\(et.perimeter)")
 et.perimeter = 9.9
 print("\(et.sideLen)")

简化:

如果只读,则可去掉set,并且可以去掉关键字 get
属性观察者。监控属性的变化
willSet —修改之前调用 newValue 参数
didSet —修改之后被调用 oldValue 参数

//如果只读,则可去掉set,并且可以去掉关键字 get

//属性观察者。监控属性的变化
//willSet ---修改之前调用   newValue 参数
//didSet  ---修改之后被调用 oldValue 参数

//举例 :属性观察者 观察变长变化
class  EquilarterTriangle {
    var sideLen :Double = 0.0{
        willSet {
            print("调用属性观察者willSet ,当前值是 \(sideLen),new value is \(newValue)")
        }
        didSet{
            print("调用属性观察者didlSet ,当前值是 \(sideLen),old value is \(oldValue)")
        }
    }
}

var et = EquilarterTriangle()
et.sideLen = 10.0
et.sideLen = 20.0

3.4 静态属性

//静态属性
//存储与类相关的数据,而不是对象数据 ,比如银行利率
//static 关键字
//形成 类的属性,类的方法,即该类对象共有
//可以由类名 直接使用,不用建立对象

下标

建立下标,直接用下标去访问属性

//下标 subscrip
//举例: 使用三角形 下标 返回三角形三边的长度

class Triangle {
    var sideLen1: Double
    var sideLen2: Double
    var sideLen3: Double
    init(sideLen1 :Double ,sideLen2 :Double , sideLen3 :Double) {
        self.sideLen1 = sideLen1
        self.sideLen2 = sideLen2
        self.sideLen3 = sideLen3
    }
    subscript(sideIndex: Int)->Double{
        switch sideIndex{
        case 1: return sideLen1
        case 2: return sideLen2
        case 3: return sideLen3
        default : return -1
        }
    }
}

var T1 = Triangle(sideLen1: 3.0, sideLen2: 4.0, sideLen3: 5.0)

print(T1[1])
print(T1[2])
print(T1[3])
print(T1[4])

3.5 继承

正如所有面向对象编程思想,继承是为了解决代码重复编写
如经典例子:
一个 Cat 类
一个 Dog 类
一个 Frog 类…
可能他们都有 属性:age (年龄)
方法:eat(进食); sleep(睡觉)
那么没增加定义一个相似的类,只有重新写一遍相关代码。

这不符合 Smart and Lazy 原则,所以采用 代码 Reuse【复用】的基本思路。
我们构造一个 Animal 类,其他的类就好像如同这个类所衍生而来,这个Animal类如同父亲一般,我们把它叫做父类,或是超类。而派生而来的叫,派生类或子类。子类直接拥有父类的属性和方法。就如同继承一般。

继承 swift特点

  1. 类可以继承其他的类 ,把父亲类的数据和方法都构造出来
  2. “:”表示 继承 关键符 ,前为子类 ,后为父类
  3. 不需要标准类根
  4. 子类重写父类 方法,只需要用 关键字 【override】标记
  5. 单继承,只能有一个父类

子类继承时构造顺序必须是:
//构造器 init 执行三步
//1.设置子类声明的属性值
//2.调用父类的构造器
//3.改变父类的属性值,其他工作如调用方法,修改父类方法在此过程

//继承
子类继承时构造顺序必须是:
//构造器 init 执行三步
//1.设置子类声明的属性值
//2.调用父类的构造器
//3.改变父类的属性值,其他工作如调用方法,修改父类方法在此过程


//实现一个正方形的类,继承了形状【nameShape】类
//重写simpleDescription 方法

class Square : NamedShape {
    var sideLen : Double
    init (sideLen:Double,name:String){
        self.sideLen = sideLen //初始化子类的属性
        super.init(name: name) //初始化父类属性,使用父类的构造函数
        numberOfSides = 4      //修改父类的属性
        // 顺序很重要
    }
    func area() -> Double {
        return sideLen*sideLen
    }
    override func simpleDescription() -> String {  //overrie 关键字 重写 父类的方法
        return "A square with side Length \(sideLen) ."
    }
}

let square = Square(sideLen: 2.0, name: "C")
print(square.area())
print(square.simpleDescription())

//便利初始化
class ClassA{
    let num :Int
    init(num:Int){
        self.num = num
    }
    convenience init(bigNum:Bool)//便利初始化器,调用初始化器,必须调用指定的构造器
    {
        self.init(num : bigNum ? 10000 : 1)
    }
}
var objA = ClassA(bigNum: true)
print(objA.num)
//required 关键字
//子类有其他初始化器的时候,必须重写

class C {
    var num: Int
    required init(num :Int){ //子类有其他初始化器的时候,必须重写
        self.num = num
    }
}
class D : C {
    let numD :Int
    let str :String
    init(str:String, num :Int) {
        self.str = str
        self.numD = num
        super.init(num: num)
    }

    required init(num: Int) {
        self.numD = num + 2
        self.str = "Hello"
        super.init(num: num)
    }
}

let objD = D(str: "FIFA", num: 20)
//其他一些知识点

//final
//类 则 不能继承
//属性方法 则 不能修改


//is 是否是某一个类型
//as

//Any 任何class的类型

//AnyObject 任何类型 (除了方法类型,函数类型)


//理解类型的判断
class Human{}
class Man : Human{}
class Woman :Human{}
let man = Man()
let woman = Woman()
var arr = [ man , woman ]
for people in arr{
    if people is Man{
        print("This is Man")
    }
    if people is Woman{
        print("THis is Woman")
    }
}

一个综合的例子;

// 综合例子:
enum Sex {
    case female
    case male
}
class Person{
    var firstName: String
    var lastName: String
    var age: Int

    var gender :Sex
    var fullName: String  { //计算属性
        return firstName+lastName
    }

    required init(firstName:String,lastName:String,age:Int,gender:Sex) {
        self.age=age
        self.firstName=firstName
        self.lastName=lastName
        self.gender=gender
    }
    convenience init(defaultData:Bool)//便利初始化器,调用初始化器,必须调用指定的构造器
    {
        self.init(firstName: "Jack", lastName: "Smith", age: 20, gender: Sex.male )
    }

    func work()  {
        print("Person \(fullName) is working.")
    }

}

class Student: Person {
    /*var sideLen : Double
    init (sideLen:Double,name:String){
        self.sideLen = sideLen //初始化子类的属性
        super.init(name: name) //初始化父类属性,使用父类的构造函数
        numberOfSides = 4      //修改父类的属性
        // 顺序很重要
    }*/
    var StuID : String
    var cScore :Int
    var cppSore :Int
    var dataStruct : Int
    init(StuID : String,cScore :Int,cppSore :Int,dataStruct : Int,firstName:String,lastName:String,age:Int,gender:Sex) {
        self.cppSore=cppSore
        self.cScore=cScore
        self.dataStruct = dataStruct
        self.StuID =  StuID
        super.init(firstName:firstName , lastName: lastName, age: age, gender: gender)
    }


    required init(firstName: String, lastName: String, age: Int, gender: Sex) {
        fatalError("init(firstName:lastName:age:gender:) has not been implemented")
    }
    subscript(sideIndex: Int)->Int{
        switch sideIndex{
        case 1: return cScore
        case 2: return cppSore
        case 3: return dataStruct
        default : return -1
        }
    }

}
class Teacher: Person {

 override func work() {
 print("Student \(fullName) is Learning.")
 }
}


var person1 = Person(defaultData: true)
var teacherForIOS = Teacher(firstName: "Doctor", lastName: "Who", age: 40, gender: Sex.male)
var student1 = Student(StuID: "2016110246", cScore: 90, cppSore: 95, dataStruct: 55, firstName: "张", lastName:"飞", age: 20, gender: Sex.male)

person1.work()
teacherForIOS.work()
student1.work()
print(student1[1])
print(student1[2])
print(student1[3])


仅为笔记 , 旨在记录,定有缺漏,有错必改


10-04 15:01