swift学习02-数据结构和类

一:可空类型

首先swift语言引进了可空类型的概念,这和objective-c是不一样的。在oc中,任何数据类型都可以是nil,但是在swift中,任何一种数据类型都有一个相对应的可空类型,下面就先展示简单的可空类型的申明和拆包装包的过程。

//定义申明
var str:String?//可空类型,在原来的类型上添加一个?
str = "asd"
print("123", separator: "123", terminator: "789")
str!.uppercaseString//可空类型不能调用(原来的方法,必须拆包),可空类型和原来的非可空类型完全是2个类型,不能直接调用原来类型的api,必须拆包(即将可空类型转换成非可空类型)

//装包和拆包
var a : Int?//定义可空类型
a = 1

func printInt(a:Int){//参数是非可空类型
    
    print("\(a)");
    
}
//拆包
printInt(a!)//强制拆包,将可空类型转换成非可空类型,精度会有丢失


func printOptionalInt(a:Int?){// 参数是可空类型
    
    print("\(a)")
}
printOptionalInt(a)//a是可空类型,不需要拆包,可以直接传递。可空的打印的是Optional(自己)

if a==nil{//只有可空类型才能跟nil做比较
    
    print("nil")
}else{
    
    print("real")
}


//装包(将非可空类型转换成可空类型)
var b:Int = 2
func printOther(a:Int?){
    
    print("\(a)")
}
printOther(b)//隐式装包。装包是自动执行的,精度不会丢失。


二:数组和字典

虽然数组在swift语言中可以元素可以不固定(一个数组中可以放几种数据类型),例如:数组可以写成:

let arrayA :Array = [1,"2","3"];//数组中放了整型和字符串2中数据结构,
虽然可以,但是不建议这样,因为这样程序的可读性和维护性太差了

建议写法:

var arrayB:Array = [1,7]//初始化必须要有值


字典在swift中有严格的定义,必须制定键值对的数据类型,否则编译不过,如下:
var dic:Dictionary?//必须指定键值对的类型
dic = ["1":"mike","2":"50"]//无论指定的键值对是什么类型,就算value指定的是非可空类型(如上:是String),但是取这个值的时候,仍然是可空类型
dic!["1"]取出的值仍然是可空的optional("mike"),而不是非可空的“mike”

字典的遍历可以用元组进行遍历,如下

for(key,value) in dic!{//要拆包
    
    print("\(key,value)")
}


三:枚举

在swift中,枚举的定义和使用跟oc并没有什么区别,下面就是swift中枚举的定义和应用的实例:

enum Week:Int{//指定枚举中的值是整型
    
    case Monday = 1
    case Tuesday
    case wednesday
    case Thursday
    case Friday
    case Saturday
    case Sunday
}
print(Week.Tuesday.rawValue)//根据枚举中的名称获取枚举值,打印值是2

enum Week2:String{//指定枚举中的值是字符串
    
    case Monday="xingqiyi"
    case Tuesday="xiangqier"
}

let i = "xingqiyi"
if let day = Week2.init(rawValue: "xingqiyi"){//根据枚举值获取枚举中的名称
    
    switch day{
        
    case .Monday,.Tuesday:
        print("\(day)")//打印的是Monday(根据枚举值获取枚举中的名称)
    }
}

enum Week3{//并不指定枚举的值
    
    case Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
}
var weekday = Week3.Friday
switch weekday{
case Week3.Friday:
    print("weekday")
case Week3.Saturday:
    print("weekend")
default:
    break
}

//枚举联合
enum Color{
    
    case RGB(Int,Int,Int)
    case RGBA(Int,Int,Int,Float)
    case CMYK(Int,Int,Int,Int)
}
var color1 = Color.RGB(102, 102, 0);
var color2 = Color.RGBA(100, 100, 10, 0.5);
print(color1)
color1 = color2;
print(color1)

四:结构体和类

结构体和类的命名是一样的,只是一个是class,一个是struct。下面看结构体的一般用法,详情见注释:

4.1 结构体

//结构体,定义一个点的结构体
struct Point{
    
    //x,y是存储属性,即有初始值的属性
    var x = 0,y = 0
    
    //isOrigin是计算属性(所谓计算属性,就是他没有初始值,它的初始值是从其他的属性计算得来的)
    var isOrigin:Bool{
        
        get{
            return x==0 && 0 == y
        }
        
        set(origin){
            
            if origin{
                
                x = 0;y = 0
            }
        }
    }
    init(x _x:Int,y _y:Int){
        
        x = _x;
        y = _y;
    }
    
    //结构体的方法中不能改变自己的属性值,必须添加mutating
    /*
    *结构体和枚举都是属于值类型,值类型不能在它自己的实例方法中改变它自己的属性值,必须在实例方法前添加mutating,初始化方法里面不需要
mutating
*类不属于值类型,因此不需要添加mutating */ mutating func addOffset(x dx:Int,y dy:Int){ x += dx y += dy } //结构体的类方法,类中的类方法只需将static关键字改成class即可 static func detaPoint(p1:Point,p2:Point) ->Point{ return Point.init(x:(p2.x-p1.x),y:(p2.y-p1.y)) } }
 
  
首先:结构体中的属性是分为存储属性和计算属性的,存储属性就是有初始值的属性,而计算属性是没有初始值的,必须通过set方法设置后才有值。其次有个很重要的概念,就是结构体和枚举都是属于值类型的,而类不属于值类型!!!!!故而,结构体中的方法不能在方法体中改变自身的属性值,必须要在方法前加mutating关键字才可以在方法中改变自身的属性值。其他跟类基本一致。

4.2 下标方法

oc中是没有下标方法的,下标方法是swift语言中特有的一种方法,在每个结构体和类中默认都会有一个subscript方法,即下标方法。你只需要实现这个方法,就可以快速的获取到实例中的某一个属性或者对象。如下是在结构体中用的下标方法。

struct Week4 {
    
    var day:Array>
    
    init(){
        
        day = [
        
            ["englishname":"Sunday","chinesename":"星期天"],
            ["englishname":"Monday","chinesename":"星期一"]
        ];
    }
    
    subscript(index:Int)->String?{//下标方法,能够快速的获取某一天的英文名
        
        let dic = day[index]
        return dic["englishname"];
    }
}

let week4 = Week4.init()
week4[0];//可以直接调用下标方法,并将下表方法的的参数设为0

4.3类以及类的继承

class Box {
    var width:Float = 0.0,height:Float = 0.0//存储变量,默认初始值都是0
    init(width _width:Float,height _height:Float){//构造器
        
        width = _width
        height = _height
        
    }
    
    func draw(){//方法,打印宽高
        
        print("I am a box with width\(width) and height \(height)")
    }
}
let box = Box.init(width: 1.0, height: 3.0)
box.draw()

class squareBox: Box {
    
    init(width:Float){//构造器
        
        super.init(width: width, height: width)
    }
    
    override func draw() {//重写父类的方法。需要添加override,另外属性也是可以重写的。但是感觉在在swift中重写属性没有什么必要,因为set和get方法都必须取super值。
        
        print("i am a squareBox with width \(self.width)")
    }
    
}
let squareBox1 = squareBox(width: 2.0)
squareBox1.draw()
print(squareBox1.width,squareBox1.height)

结构体和枚举都是值类型,不存在什么继承,继承只是类的特性。



你可能感兴趣的:(swift之路)