Swift笔记 3.0
初探类与对象
类,函数,闭包,枚举,结构体
overview:
swift 是一个极具面向对象特征的编程语言 , 她有Class ,Object , Attribute and Method 这些典型的面向对象的特点和结构,广义上她可以作为面向对象方式来开发,虽然她实际上更特别于她的面向协议的特点,但其中也离不开面向对象的基础建立,这里首先介绍一下 Swift 4 下的 面向对象的一些基本编程组建方法 。
文章目录
- Swift笔记 3.0
- overview:
- 3.1 类定义
- ps: swift中 类 和 结构体 的区别
- 3.2 类的 初始化器
- 3.3 类的属性
- 3.4 静态属性
- 下标
- 3.5 继承
- 子类 继承时 构造顺序
- 便利初始化
- required 关键字
- 其他一些知识点
- 3.6 一个综合的例子;
3.1 类定义
类定义
实例化
// 4 类与对象
// 定义 类
class Shape {
var numberOfSides = 0 //成员变量 (属性)
func desicriotion(){ //成员函数 (方法)
print("A shape with \(numberOfSides) sides.")
}
}
// 创建类对象,使用
var s = Shape()
s.numberOfSides = 6
s.desicriotion()
ps: swift中 类 和 结构体 的区别
结构体不能被继承,类可以
他们都能拥有方法
结构体 ---- 值类型
类 ---- 引用类型
//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特点
- 类可以继承其他的类 ,把父亲类的数据和方法都构造出来
- “:”表示 继承 关键符 ,前为子类 ,后为父类
- 不需要标准类根
- 子类重写父类 方法,只需要用 关键字 【override】标记
- 单继承,只能有一个父类
子类 继承时 构造顺序
子类继承时构造顺序必须是:
构造器 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 关键字
子类有其他初始化器的时候,必须重写
//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")
}
}
3.6 一个综合的例子;
// 综合例子:
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])