Swfit入门教程9-类和结构体

原创blog,转载请注明出处

http://blog.csdn.net/hello_hwc

之所以把这两个放在一起,是因为在swfit中,类和结构体的关系非常紧密,甚至很多时候很难区分是用类实现还是用结构体实现好。

在其他语言中,类对应对象,而在swfit中,常常称作类对应实例,结构体也对应实例。

一、类和结构体的异同
1、都可以定义属性存储值
2、都可以定义方法提供功能
3、都可以定义构造函数
4、都可以定义附属脚本
5、都支持扩展和协议

相对于结构体,类具有如下功能
1、类允许继承
2、类允许动态类型检查
3、类允许析构器释放资源


有一点要始终记住,类传的是引用,结构体传的是值,也就是copy;
以下情况比较适合使用结构体
1、应用在存储和传递少量相关数据,并且传递值,而不是引用;(大部分情况下考虑的是这一点)
2、不需要继承

二、类和结构体简析
定义
class HwcClass{
var classVariable = 0
func print(){
println("From class")
      }
}
struct HwcStruct{
  var structVariable = 1
func print(){
println("From struct")
}
}

这里要养成一个命名习惯,类名的开头用大写字母,属性和方法的开头字母用小写
然后按照每个单词首字母大写:例如:var firstVariable

声明完类之后,用构造器创建实例
var someHwcClassInstance = HwcClass()
var someHwcStructInstance = HwcStruct()
用点(.)来访问类或者结构体的属性和方法
var classVariable =  someHwcClassInstance.classVariable 
var structVariable =  someHwcStructInstance.structVariable 
someHwcClassInstance.print()
someHwcStructInstance.print()
这里要提到的是,与Objective-C不同,swfit允许直接修改结构体的某一个子属性,另外array
和dictionary内部都是结构体实现的,所以他们不属于AnyObject

判断类和结构体是否想“相等”
对于类来说,是引用类型,所以是否相等要看两个引用是否相同
swift提供===和!==盘判断是否等价于,也就是说是否是同一个引用
对于结构体来说,是值类型,所以是否相等看两个结构体内容是否相等
采用==和!=来判断

三、属性
swift中把objecti-C中的属性定义都简化成一个语句
命名 类型 内存管理特征
1、存储属性-可以在class struct中使用
用来存储值,可以是常量,可以是变量
可以在定义的时候指定初值,也可以在构造的时候赋予初值(对let类型的属性也使用)
class csdnID{
    var name:String = “jack”
    let ID:String = "123456"
    init(name:String,ID:String){
	self.name = name;
	self.ID = ID	
}
}
var myID = csdnID(name:"HelloHwc",ID:"12345568")
myID.name = "CallMeHwc"
//myID.ID = "1234556" wrong
因为,用户名可以修改,但是系统赋予给用户的识别ID不能修改,对于不想修改的,我们只需要在生命中声明为let即可,注意,及时是let,可以在构造的时候进行赋值

2、延迟属性
关键字lazy
在需要的时候才进行初始化,构造的时候无需进行初始化,但是对延迟属性要指明构造器。
适用于:
(1)当属性的值需要于复杂或者大量计算时
(2)当属性值依赖于外部因素时
(3)当属性值不确定是否会被使用到时
class CSDN{
	lazy lazycoder:NSMutableArray = NSMutableArray(array:["jack","lucy","tom"])
	//Something else
}
当我们想要使用这个lazy变量的时候直接使用,因为我们不是每一次都要知道那些人lazy,所以不需要每次在构造的时候都初始化这个变量。
var instance = CSDN()
var lazyCoders = instance.lazycoder

3、计算属性-可以在class struct enum中使用
计算属性在内存中并不保存属性
通过getter来获取值
可选setter来进行间接赋值
class Line{
    let startPoint:Int = 0
    var endPoint:Int = 15
    var centerPoint:Int{
        get{
            return startPoint+endPoint/2
         }
         set(newCenter){
            endPoint = 2*newCenter - startPoint
         }
    }
}

swift中,对setter方法,可以使用默认的newValue作为传入值
class Line{
    let startPoint:Int = 0
    var endPoint:Int = 15
    var centerPoint:Int{
        get{
            return startPoint+endPoint/2
        }
        set{
            endPoint = 2*newValue - startPoint
           }
    }
}

var line1 = Line()
println(line1.endPoint)
println(line1.centerPoint)
line1.centerPoint = 10
println(line1.endPoint)

如果不提供set方法,则centerPoint为只读属性
class Line{
    let startPoint:Int = 0
    var endPoint:Int = 15
    var centerPoint:Int{
    get{
        return startPoint+endPoint/2
    }
    }
}
var line1 = Line()
line1.centerPoint = 10//Wrong

4、属性观察器
属性观察器响应值得变化,每次赋值的时候(就算值没有变化),属性观察期都会被调用。但是不
包括初始化的时候。
两个观察器,
willSet 在属性设置前调用;默认会将新的值作为擦书传入,如果不指定,默认为newValue
didSet  在属性已经被设置后调用;默认旧值传入,不指定的话,默认oldValue
class Test{
    var testVar:String = "oldvalue"{
    willSet{
        println("Value to be set is \(newValue)")
    }
    didSet{
        println("Old value is \(oldValue)")
    }
    }
}
var instance = Test()
instance.testVar = "newvalue"
可以看到输出是
Value to be set is newvalue
Old value is oldValue

5、类型属性-适用于struct enum
类似于C++中的static属性,就是该属性隶属于类,调用的时候直接通过类型名调用,不需要实例化。
对于struct和enum,类型属性由关键字static声明
何时使类型属性:就是本身这个属性和对象无关,比如我接下来的类型描述就与对象无关;,
struct Point{
    var x:Int = 0
    var y:Int = 0
    static var description:String = "This is a struct about Point"
}
println(Point.description)

四、方法
Swfit中可以为类,结构体和枚举定义方法,这也是swfit相对于objective C的改动之一
方法分为两种
实例方法:通过实例调用
类型方法:通过类名调用 关键字和类型属性一样,用static 和 class来声明
1、实例方法
调用的时候通过.来调用
其中self为实例本身,类似C++中的this指针
简单的例子
struct PersonInfo{
    var name:String;
    var id:String;
    func showInformation(){
        println("\(name)\n\(id)")
    }
}
class MyCSDN{
    var info:PersonInfo
    var visitTimes:Int
    init(info:PersonInfo,visitTimes:Int){
        self.info = info //用self来区分
        self.visitTimes = visitTimes
    }
    func showCSDNInfo(){
        info.showInformation()
    println(visitTimes)
    }
}
var onePerson = PersonInfo(name:"hwc",id:"7865123")
var myCsdn = MyCSDN(info:onePerson,visitTimes:6800)
myCsdn.showCSDNInfo()
可以看到输出
hwc
7865123
6800


2、局部和外部参数名称
局部参数供函数内使用
外部参数供调用的时候使用
swift默认为方法的第二个参数开始提供外部参数,如果想要第一个参数也作为外部参数,可以加上#
举例
class CSDN{
    func testWithFirst(first:Int,second:Int){
        println(first+second)
    }
}
var instance = CSDN()
instance.testWithFirst(1,second:2)
当第一个参数不提供外部参数的时候,通常会在函数名中用with,by等表明第一个参数是干嘛的
当然,我们也可以添加一个#让其作为外部参数使用,这时候名称就不需要像上面那样,指明第一个参数是做什么的
class CSDN{
    func testWith(#first:Int,second:Int){
        println(first+second)
    }
}
var instance = CSDN()
instance.testWithFirst(first:1,second:2)
3、mutating关键字
对于结构体和枚举来说,因为其都是值类型,所以一般情况下不允许实例方法修改其值。
如果确实需要修改,则可以选择mutating这个方法,在方法调用后,改动会保存在实例中。
struct Line{
    var startPoint:Int = 0
    var endPoint:Int = 15
    mutating func changeEndPoint(newValue:Int){
    endPoint = newValue
    }
}
var line = Line()
line.changeEndPoint(20)
println(line.endPoint)
4 类型方法
对于class使用关键字class
对于struct enum使用关键字static 

举例

private var name:String = "Hello_hwc"
class CSDN{
    class func print(){
        println(name)
    }
}
CSDN.print()

ADD:由于swift语言版本更新的问题,暂时不支持在class中声明实例变量了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值