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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5.Swift枚举|结构体|类|属性|方法|下标脚本|继承相关的知识,希望对你有一定的参考价值。

  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()

 

 

}

以上是关于5.Swift枚举|结构体|类|属性|方法|下标脚本|继承的主要内容,如果未能解决你的问题,请参考以下文章

结构体,枚举类型

Swift2.0结构体类型&枚举类型

➽08结构体与类

➽08结构体与类

☀️ 学会编程入门必备 C# 最基础知识介绍——数组字符串结构体枚举类

Swift23-访问控制