5.Swift枚举|结构体|类|属性|方法|下标脚本|继承

2023-04-25,,

1. 枚举:

->在Swift中依然适用整数来标示枚举值,需搭配case关键字

enum  Celebrity{  case DongXie,XiDu,Nandi,BeiGai }  // 从左到右对应0,1,2,3

enum CompassPoint {

case North

case South

case East

case West

//enum中可以定义方法

func show(){

print(self)

}

}

//定义enum 变量

var p = CompassPoint.North

var p2 = CompassPoint.South

p.show()

p2.show()

var point:CompassPoint = .West

switch point{

case .North:

print("北")

case .South:

print("南")

case .East:

print("东")

case .West:

print("西")

}

enum Week:Int {

case Sun, Mon, Tur, Wen, Thu, Fri, Sat

}

//原始的(裸值)需要进行类型标注,

// notice:这里通过调用枚举类型  Week 调用 枚举成员Sun 裸值(及C中所述的枚举整型值),需要在赋值的变量后面加上的的类型标示符号

var  weekDay:Int = Week.Sun.rawValue

//也可以直接通过Week的 rawValue方法调用得道当前的 枚举成员

var week:Week? = Week(rawValue:7)  //这里如果rawValue 超出了枚举值的返回,则返回为空,所以week需要使用可选值来接收

//还可以利用元组特性设置关联的枚举成员

enum BarCode {

case UIPCA(Int,Int,Int)  //条形码

case QRCode(String)     //二维码

}

//定义个枚举变量

var barcode = BarCode.UPCA(690,3322323,2)

barcode = Bar.QRCode("http://fdsafdsfa.com")

switch barcode {

case BarCode.UPCA(let(num,id,check)):

print("这是一个条形码 \(num)-\(id)-\(check)")

case BarCode.QRCode(let string):

print("这是一个二维码 对应的字符串是:\(string)")

}

}

/**使用新的写法,在绑定变量的同时,指定条件判断,类似于SQL*/

switch aPoint {

//在绑定一个变量的同时,可以绑定x == y

case let(x,y) where x == y:

print("x 与 y相等斜线上 x = y")

case let(x,y) where x == -y:

print("x 与 -y斜线上 x = -y")

default:

print("other")

}

2. 结构体和类:

相同点:

结构题和类,都在定义一种类型

都可以在内部定义属性和方法

都可以定义下标运算符

都可以定义初始化方法(Int 初试化器,  构造器  构造方法)

都可以使用扩展现有的功能(OC中有分类,Swift中没有分类,叫扩展)

都可以遵循制定的协议

不同点:

类可以继承,结构体不能

类有多态,结构体没有

类的内存支持自动引用技术,结构体不支持引用技术,结构体变量都是在栈中分配内存空间,不需要手动管理

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

//属性的初始化就提供了一个无参 和统一的初始化器

struct Resolution {

var width = 0.0

var height:Float = 0.0

}

//类中申明属性必须进行初始化,除非它是可选值

class VideoMode {

var resolution = Resolution()

var interlocaed = false

var frameRate = 0.0

var name:String?

}

//结构体是值类 类是引用类型

var res = Resolution()

var res2 = res

res.width = 1024

res2.width

var vmode = VideoMode()

var vmode2 = vmode

vmode.name = "zhanshang"

vmode2.name

/** ===比较地址是否相等*/

if vmode === vmode2 {

print("两个引用是同一个值")

}

if vmode2 !== vmode {

print("两个引用不是同一个地址")

}

/** 结构体的统一初始化器,这与C中的结构题嵌套非常相识,紧紧是指把变量的定义方式改变了一下,另外支持 点语法访问层级嵌套属性*/

struct Point {

var x :Float

var y :Float

}

struct Size {

var w :Float

var h :Float

}

struct Rect {

var origin: Point

var size: Size

}

var rect = Rect(origin: Point(x: 100, y:20), size: Size(w : 2 ,h: 3))

rect.size.w

rect.origin.x

3. 属性,在Swift中属性有两个分类方式

第一种方式:

/**

1. Swift中属性有两个分类方式

第一种方式:

-> 存储属性(Stored Properties):用变量或者常量来保存属性值

-> 计算属性(calculate Properties): 通过计算得来的。

举例:

出生日期: 存储树形 , 年龄:需要通过两个时间进行计算

-> 第二中分类方式:

实例属性 和 类型属性

*/

// 存储属性

struct MyRange {

var location:Int

let length:Int

}

var myRnage = MyRange(location: 0, length:100)

struct Point {

var x = 0.0, y = 0.0

}

struct Size {

var w = 0.0, h = 0.0

}

struct Rect {

//存储属性,使用变量或者常量来保存存储属性

var orign = Point()  //创建 point对象

var size =  Size()

var center: Point {

get{

let centerX = orign.x + size.w * 0.5

let centerY = orign.y + size.h * 0.5

return Point(x: centerX, y: centerY)    //返回一个point类型

}

//这里如果没有参数 则使用默认的 newValue

set{

let newOrignX = newValue.x - size.w * 0.5

let newOrignY = newValue.y - size.h * 0.5

orign = Point(x: newOrignX, y: newOrignY)    //实现origin的赋值

}

/* set(newCenter){

let newOriginX = newCenter.x - size.w * 0.5

let newOriginY = newCenter.y - size.h * 0.5

origin = Point(x: newOriginX, y: newOriginY)

} */

//假设做一个只读的计算属性

}

//如果只读计算属性,只有一行代码可以省略return

var center2:Point {

get {

return Point(x: 500 + 100,y: 100)

}

}

}

var rect = Rect(orign:Point(x: 0, y: 0), size: Size(w:300,h: 200))

rect.center.x

rect.center.y

rect.center = Point(x: 200, y: 200)

rect.orign.x

rect.orign.y

/** 延迟属性 类似 OC的懒加载,或者延迟加载*/

class DataImporter {

init(){

print("DataImporter create")

}

var fileName = "data.txt"

//这个需要用到的时候才去加载

}

class DataManager {

lazy var dataImporter = DataImporter()

}

//创建DataManager这个对象

var dataManager = DataManager()

/**在需要执行懒加载的属性前面加上layz*/

dataManager.dataImporter

4. 属性监视器:是一段代码,这段代码会在属性发生变化的时候自动调用

->计算属性,延迟属性,不能设置监视器,只有存存储属性才能设置监视器

->属性监视器,在属性初始化的时候不调用

->属性监视器有两种,willSet,didSet

class StepCounter {

var labelText = " text content"

/**storeage property*/

var  a :Int = 10

//只读计算属性

var b:Int {

return 10

}

// 给属性 加属性监视器

var totalSteps:Int = 10 {

willSet (newValue){

print("属性将要变化时调用 要改变成\(newValue) 现在是\(totalSteps)")

}

didSet{

print("属性值已经发生改变了嗲用原来的值时\(oldValue)现在是\(totalSteps)")

labelText = "改变的值时\(totalSteps)"

}

}

}

var propertyName:Int = 10{  willSet(newValue){ //inserCode here  }  didSet{  //insertCode here } }

var stepCounter = StepCounter()

stepCounter.totalSteps = 50

stepCounter.labelText

stepCounter.totalSteps = 20

stepCounter.labelText

5. 类型属性:

在结构体或者枚举中,使用static修饰的属性以及在类中使用class关键字修饰的属性叫做类型属性,属于整个类和对象无关。

在struct 中定义的类型属性,可以是存储属性,也可以是计算属性

在class 中定义的类型属性,只能是计算属性(如果需要使用存储树形座位设计类型属性,可以加上static关键字)

struct SomeStrut {

//存储属性

var a = 10

//计算属性

var b:Int {

return 10

}

//类型属性

static var x = 10

static var y:Int {

return  10

}

}

var someStruct1 = SomeStrut()

someStruct1.a    //10

var someStruct2 = SomeStrut()

someStruct2.a    //10

SomeStrut.x   //10

SomeStrut.y   //10

class SomeClass {

var a = 10

var b :Int {

return 10

}

/** 类型属性,太奇葩了*/

static var y :Int {

return 100

}

class var x:Int {

return 100

}

static var storeagePorperty:Int = 10 //编译通过。优先使用static

// Swift编译无法通过❌class var storagePorperty1:Int = 100

}

SomeClass.y

SomeClass.storeagePorperty = 123

SomeClass.x

6.实例方法,类方法,几乎同OC一样

//实例方法 与类方法,类中的实例方法几乎和OC一样

/** 类类型的实例方法*/

class Counter{

var count = 0

func increment(){

count++

}

func incrementBy(amount: Int){

count += amount

}

func incrementBy(amount: Int ,numberOffTimes: Int) {

count += amount * numberOffTimes

}

}

/** create a instance */

var counter = Counter()

/** invoke instance method*/

counter.increment()

/** 值类型的实例方法 */

struct Point {

var x = 10, y = 10  //实例 值类型属性,由对象调用,或者对象 self指针调用

var z = 250

static var sx = 10   //类类型属性,由类调用,或者类 self指针调用

func show() {

print("点点\(x)")

Point.sx = 1111

}

//值类型的实例方法,默认不可以修改实例属性,如果非要修改则加上mutating

mutating func setX(px: Int,AndY y:Int) {

// x = px

self.x = px

//防止参数和属性重名

self.y = y

Point.sx = 111

}

}

enum StatusSwitch{

case Study,Dining,Review,Sleep

func show(){

switch self{

case .Study:

print("正在学习")

case .Dining:

print("正在吃饭")

case .Review:

print("正在复习")

case .Sleep:

print("正在睡觉")

}

}

/** 切换状态, 这里如果想修改self需要在前面加上 mutating*/

mutating func nextStatus(){

switch self {

case .Study:

print("下一步吃饭")

self = .Dining

case .Dining:

print("下一步 去复习")

self = .Review

case  .Review:

print("下一步 去睡觉")

self = .Sleep

case .Sleep:

print("下一步 去学习")

self = .Study

}

}

}

var ss = StatusSwitch.Study

ss.show()

ss.nextStatus()

ss.nextStatus()

ss.nextStatus()

ss.nextStatus()

ss.nextStatus()

ss.nextStatus()

ss.nextStatus()

ss.nextStatus()

7. 类型方法:

//类型方法 和 OC中的类方法,含义相同

class SomeClass {

var prop:Int = 0   //实例属性必须要有了对象之后能方位

class var a:Int {   //类属性 ,class也可以使用static

return 10

}

func instanceMethod() {

print("this is a instance method")

self.prop

SomeClass.a

//self.a  a为类属性,所以无法调用

}

class func typeMethod(){  // class func 代表定义个类方法

print("这是一个类型方法")

//同OC,类方法中不能访问实例属性,但是可以访问类型属性

// self.prop

self.a  //self带表调用这个方法的对象,self相当于调用类方法的对象,类对象

SomeClass.a

}

}

var p = SomeClass()

p.prop

SomeClass.a

//类方法的调用

SomeClass.typeMethod()

//先创建一个类的对象-》

var instanceObject = SomeClass() //类名+()可以创建一个类的对象

instanceObject.prop

instanceObject.prop = 10

instanceObject.prop

struct SomeStruct {

var prop:Int = 0

/**声明一个static的存储属性*/

static var a: Int = 0

func show(){}

func instanceMethod(){

//此处实例属性可以读但是不能修改   prop = 1000,如果需修改采用

self.show()

print(prop)

}

/**结构体中, 类方法使用static,在类中可以使用static和class定义类方法和变量方法, C++里面叫做静态方法,但是在结构体中只能是static */

static func typeMethod(){

print("这是一个类型方法")

//self.show() 实例方法,❌,此处无法使用

}

}

/**枚举中 类型方法*/

enum StatusSwitch {

case Study,Dinig,Review,Sleep

static func typeMethod() {

print("这是一个类型方法")

}

static func create()->StatusSwitch {

return self.Study  //StatusSwitch 类对调用 create 类方法,self 指向StatusSwitch,所以返回为StatusSwitch类型

}

func show() {

print("这是一个实例方法")

}

}

StatusSwitch.create().show() //

StatusSwitch.Study.show() //与上面等价   //枚举成员可以调用枚举类的方法,这样理解会好记一点,搞不明白的就暂时当成一种格式来记,等代码积累量上去了再回过头来研究。

8. 下标脚本,主要用于检查数组边界是否越界;使用断言的方式

class MyArray {

//private 私有的,越界返回真,不越界返回假

pravate var array = [0,1,2,3,4,5,6,7,8,9]

func indexIsValid(index:Int) -Bool {

if index < 0 || index >array.count - 1 { return ture } else { return false }

/**增加数据*/

func addObjectAtIndex(index:Int ,object:Int) {

assert(indexIsValid(index))

array.insert(object,atIndex:Index)

}

func show(){   print(array)  }

}

//让MyArray支持下标,写法一

定义一个 通过subscript构建一个整型的下标函数,创建set 和 get方法,其中set方法中newValue和数组赋值时,外界传入的形参

subscript(index:Int)->Int {

get {  return array[index] }

set {  array[index] = newValue }

}

方法二:通过改写set方法

subscript(index:Double)->Int {

get{ return  array[Int(index + 0.5)]}

set{  array[Int(index + 0.5)] = newValue }

//此处的newValue为set方法调用时外部带的参数 类似于 (int)setnewValue:(int)newValue

}

var myArray = MyArray()

myArray.show()

myArray.addObjectAtIndex(1, object: 100)

myArray.show()

myArray.array + [30,300]

myArray.array.removeAtIndex(5)

myArray.show()

myArray.array[0]

9. 继承:

父类 子类 (基类,派生类)

Swift中的特点: 一个类可以没有父类,不像OC所有的类都继承于NSObject,Swift中是单即成类,一个类只能由一个父类,但是可以有多个子类。

class Vehicle {

//存储属性  storage properties

var currentSpeed = 0.0

//计算属性 calculate properties

var description:String {

return "当前速度是每小时\(currentSpeed)公里"

}

func makeNoise() {

print("父类发生的方法")

}

func show(){

print("父类显示的方法")

}

}

/** inheritance*/

class Bicycle: Vehicle {

/** extension propertie*/

var hasBasket = false

/** extension method*/

func test(){

print("subClass extension method")

}

/** override parent method*/

override func makeNoise() {

print("subClass dong dong ...")

}

}

var bike = Bicycle()

bike.show()

bike.makeNoise()

bike.hasBasket

bike.currentSpeed

/**父类型指向子类型,前面obj为交通对象,makeNoise重写后被覆盖,先调用子类的方法

*/

var obj:Vehicle = Bicycle()

obj.makeNoise()

}

/**

覆盖父类的方法只需要在方法前面使用override关键字, override func 。。。。

重写父类属性只需要在子类定义与父类相同的属性,并在后面加上{  didSet{  //inertCode 需要重写的内容 } }

在父类中 变量和方法前面只要加上 final关键字则表示该方法不能被重写

*/

class  Car : Vehicle{

var  gear = 1

// 重写覆盖父类的方法

override func  makeNoise(){

print("汽车滴滴")

}

// 重写计算属性

override var  description : String {

return  super.description + "在\(gear)档上"

}

// 重写父类的存储属性

override var currentSpeed : Double{

didSet{

gear = Int(currentSpeed/10.0) + 1

}

}

}

var  car = Car()

car.gear

car.currentSpeed = 40

car.description

car.gear

/*final */ class Base { // 限制这个类不能被继承

final var  a = 10 // final 不能被重写

final func show(){ } //final 的方法不能被重写

}

class Child: Base {

}

// 开发中还有一种常见的形式 组合

class Radio{

var  price : Double = 0.0

func radio(){

print("收听广播")

}

}

class  MyCar{

var radio = Radio()

}

var  mc = MyCar()

mc.radio.radio()

mc.radio.price = 10000000

5.Swift枚举|结构体|类|属性|方法|下标脚本|继承的相关教程结束。

《5.Swift枚举|结构体|类|属性|方法|下标脚本|继承.doc》

下载本文的Word格式文档,以方便收藏与打印。