【极客班】Swift高级编程二
结构与枚举
类与结构的异同:
相同点:都可以定义以下成员:属性、方法、下标、初始化器;都支持类型扩展、协议。
不同点:类支持继承和多态,结构不支持;类必须自己定义初始化器,结构会有默认的按成员初始化器;类支持析构器,结构不支持;类的实例在堆上,有ARC负责释放;结构的实例在栈上,栈结构自动释放,不参与ARC管理;类支持引用相等比较,结构不支持。
枚举:
enum属于值类型,有值拷贝语义;可以用switch-case语句处理,但case必须包含所有枚举值,否则需要default:
//定义枚举类型
enum Color {
case Red
case Green
case Blue
}
enum ComplexColor{
case Red,Green,Blue,Alpha
}
同样可以为enum指定原始值,即raw value,类型可以是字符、字符串、整数、或浮点数;数值默认从0开始,字符串与枚举值名称相同:
//指定原始类型
enum WeekDay: Int{
case Monday=1, Tuesday, Wednesday,Thursday, Friday, Saturday, Sunday
}
var day: WeekDay?
day = WeekDay(rawValue: 7)
var data=WeekDay.Saturday.rawValue
enum支持关联值,可以设置不同类型的值成员,类似联合数据结构:
class Point{
var x=0
var y=0
init(x:Int, y:Int){
self.x=x
self.y=y
}
}
//枚举关联值
enum Position{
case Number(Point)
case Name(String)
}
var p1=Position.Number(Point(x: 123,y: 588))
var p2=Position.Name("Shanghai People's Square")
继承与多态
继承:子类自动继承基类的属性、方法、下标;只有类支持继承,结构和枚举不支持继承;继承同时支持实例成员和类型成员:
class Shape{
var no=0
func move() {
print("NO: \(no) Shape.move")
}
}
class Rectangle: Shape{
var leftUp=Point()
var width=0
var height=0
}
class Circle: Shape{
var center=Point()
var radius=0
}
多态:
子类在同一行为接口下,表现不同的实现方式;子类使用override关键字来表示多态定义,也可以使用super来调用基类的实现:
class Shape{
var no=0
//0x000340
final func show(){
print("Shape.show")
}
//0x000640
func move() {
print("Shape.move")
}
}
class Rectangle: Shape{
override var no: Int {
get{
print("Rectangle.no.get()")
return super.no
}
set{
print("Rectangle.no.set()")
super.no=newValue
}
}
//0x000880
override func move() {
print("Rectangle.move")
}
}
继承中的初始化器init:如果子类没有初始化器,则自动继承;如果子类初始化器与基类初始化器原型一致,必须使用override;在子类中使用基类属性,必须确保首先调用基类初始化器;
继承中的析构器deinit:如果子类没有定义析构器,会自动继承基类析构器;子类析构器执行完毕后,会自动调用基类析构器;子类析构器自动具有多态性;
class Base{
var data1:Int
init(){
data1=100
print("\(data1)")
print("Base.init")
}
deinit{
print("Base.deinit")
}
}
class Sub: Base{
var data2=200
override init(){
super.init()
print("\(data1), \(data2)")
print("Sub.init")
}
deinit{
print("Sub.deinit")
}
}
协议
类型的合同约定,只描述外部接口,不提供具体实现方法
协议可以包含以下成员:
属性(协议中可以定义只读属性,也可以定义读写属性;协议中可以定义实例属性、也可以定义类型属性;协议中只能定义变量属性,不能定义常量属性;实现协议时,并不要求实现为存储属性、还是计算属性);
方法(协议可以定义实例方法、也可以定义类型方法;协议中的方法不能定义参数的默认值);
初始化器;
下标;
操作符;
一个类型可以实现多个协议,协议可以应用在如下类型上。但可以添加class关键字标明协议只能应用在类上:
类;
结构;
枚举;
//定义协议
protocol Drawable{
var discription: String{
get
}
func draw()
init()
subscript(index: Int) -> Int {
get
}
func ==(lhs: Self, rhs: Self) -> Bool
}
//实现协议
final class Point: Drawable{
var x:Int
var y:Int
init(){
x=10
y=10
}
var discription: String{
return "[\(x), \(y)]";
}
func draw(){
print(self.discription)
}
subscript(index: Int) -> Int {
return 0
}
}
协议本质上是一种类型,可以作为声明类型,但不能创建实例。
协议变量的内存模型遵从实际类型的内存模型:
引用类型传参、拷贝采用引用方式;
值类型传参、拷贝采用传值方式;
protocol Shape{
var discription: String{
get
}
mutating func moveTo(x:Int, _ y:Int)
}
class Point: Shape{
var x=10
var y=20
func moveTo( x: Int, _ y: Int) {
self.x=x
self.y=y
}
var discription: String{
return "[\(x), \(y)]"
}
func display(){
print(self.discription)
}
}
检查协议类型
使用is检查类型是否实现了协议:
if(item1 is AProtocol){
print("the runtime type of item1 conforms Shape protocol")
}
if(item2 is AProtocol){
print("the runtime type of item2 conforms Shape protocol")
}
使用as?和as!将类型下溯转型为协议:
item3 = item1 as? AProtocol
item3 = item2 as? AProtocol