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

    }

     /**

    覆盖父类的方法只需要在方法前面使用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

  • 相关阅读:
    latin1字符集的数据转换为utf8字符集
    mysql使用utf8mb4经验吐血总结
    字符集GBK和UTF8的区别说明
    10分钟学会理解和解决MySQL乱码问题
    MySQL大小写敏感总结
    分区表基本类型
    form表单提交的几种方法
    Redis面试题及分布式集群
    ELK
    Linux下的crontab定时执行任务命令详解
  • 原文地址:https://www.cnblogs.com/XieMinQiang/p/5275808.html
Copyright © 2020-2023  润新知