/*
属性:Property
Stored property:存储变量的属性,可以存在于类,结构体中,但枚举不能有stored property
var定义变量属性,let定义常量存储属性。可以赋初值。可以在类,结构体的初始化(构造)函数
中修改属性,包括常量属性
Lazy Stored Property:类或结构体在initialize后,仅在下次被使用前才被计算。
定义方法是在前面加上rlazy,显然lazy只能用在var,不能用在let
当某属性依赖于经常发生变化的外部数据,或者是计算非常复杂耗时,给他加个@lazy吧。
Computed property:通过计算得到的属性,可以存在于类,结构体,枚举中。
这些属性不是直接赋值的,而是通过提供getter和setter函数通过计算的得到的。
property observer:属性被赋值是,提供一个钩子进行特殊设置。
✨✨✨不能给一个属性即添加get/set又添加willset/didset,如果想监控又get/set的属性,直接在set中操作即可。
Type property:同其他语言中的静态变量,但是定义不同。
类暂时只支持computed property定义成TypeProperty的。类用关键字class,value类型的用关键字static。
*/
struct TestStruct {
var mmbV = 3
let mmbC = 4
}
class TestClass {
lazy var mmbV = 3//LazyStored Property
/*lazy*/ let mmbC = 4 //这个不能lazy,因为其本身在初始化后是不变的,没有必要。
}
let s = TestStruct()
//s.mmbV = 5 //同数组等值类型数据一样,Const的结构体是不能给成员赋值
//但是引用型的类则不同,赋值给const后,其本身是const的,但是可以修改类中的属性
let c = TestClass()
c.mmbV = 5
// c = TestClass() 赋值失败,c本身是const的。
//computed property
//顾名思义其为计算出来的值,那么说明该值是不固定的,所以必须用var,不能用let
struct Point {
var x:Int = 1
var y:Int = 2
}
class Rect {
var width = 1
var height = 2
var origin = Point(x:3, y:4)//还有结构体才可以这样赋值,类是不可以的。
var center : Point
{
get
{
println("call getter function")
let newx =origin.x +width / 2
let newy =origin.y +height / 2
return Point(x:newx, y:newy)
}
//这个可以简写为 set 这样默认参数就是变量名area
//如果不定义set函数,则对应的成员变量为只读属性
set(newCenter)
{
println("Call setter function")
origin.x = newCenter.x -width / 2
origin.y = newCenter.y -height / 2
}
}
}
var rect =Rect()
println(rect.center)//call getter function
rect.center =Point(x:10, y:20)//call setter function
println(rect.center)
//✨✨getter的设计是当前属性返回的是通过别的属性计算出来的,不能包含自己
// 如Rect类的center属性的getter中,不能用center属性参与计算
//setter的设计是将此设定通过计算后,设置其他的属性,不能修改自己。
// 如Rect类的center属性的setter中,不能给center赋值
//下面的情况会报错
/*
class ERRORRect {
var width = 1
var height = 2
var origin = Point(x:3, y:4)
var center : Point
{
get
{
let newx = center.x / 2 //ERROR "Attempting to access 'center' within its own getter"
let newy = origin.y + height / 2
return Point(x:newx, y:newy)
}
//这个可以简写为 set 这样默认参数就是变量名area
//如果不定义set函数,则对应的成员变量为只读属性
set(newCenter)
{
center = newCenter //ERROR "Attempting to modify 'center' within its own setter"
}
}
}
*/
//定义只读的属性可以把get去掉,直接写计算本体。简写方式如下
class ReadOnlyAreaSquare
{
var width = 1
var height = 2
var area : Int
{
return width * height
}
}
//Property Observer
//该功能提供了对属性设定的监视功能,定义方法同get,set类似,有两个函数可以选择
// willSet 在变量赋值前被调用,函数参数被传进来的是新设定的值,如果不写参数,默认参数名为newValue
// didset 在变量赋值后被调用,函数参数被传进来的是原来的值,如果不写参数,默认参数名为oldValue
// lazy不可以设定Observer,其他的都可以,包括从父类继承的属性,也可以重写。
// 注意,如果不是继承的有setter的函数,直接在setter中监视即可,不需要再重新定义observer函数
class Number
{
var n:Int = 3//语法格式长的跟getter setter相似
{
willSet(myNewValue) //如果只写willSet 则默认有个参数newValue
{
println("willSet data\(myNewValue)")
}
didSet //默认参数oldValue当然你也可以设置自己的参数名 myOldValue
{
println("didSet data\(oldValue)")
if(n > 10) //didset是已经对n赋值过的,这时可以对n进行有效值判断
{
println("Data is to large, set to 10")
n = 10 //通过这个观察,可以对赋值进行有效的控制。
}
}
}
}
var n = Number()
n.n = 20
println("At last the n.n is\(n.n)")
//Type property
//所谓的类型属性实说这个属性是属于你新创建的类型的,而不是属于某个实例
//和其他语言中的静态成员变量类似,但又有一些特殊的规定:
//值类型的类型用struct等定义的类型可以为stored和 computed属性定义静态变量
//✨✨但是类只能为computed属性定义静态变量。
//静态的存储成员变量必须总是赋初值,因为再类型的Initialize函数中不能给静态变量赋值
enum MyEnumType
{
static var storedTypeProperty ="必须赋初值"//只有值类型才可以。
static var coputedTypeProperty:Int
{
//
}
}
class MyNewClassType
{
var notClassMember:Int;
//类目前只能定义静态computedType变量,而静态的get中不能访问非静态的成员变量,只能进行一些常量计算
//另外,带class的属性和不带class的属性是不同的类型,不存重复定义,而是overload
class var coputedTypeProperty:Int
{
get{
//可以改善父类的属性,也可以修改其他的静态成员(目前类不能定义stored的静态成员。)
return super.coputedTypeProperty +1
}
}
}
struct MyStruct
{
static var globalStructNumber = 0;
func testStructNumber()
{
if MyStruct.globalStructNumber > 2//静态变量使用方法,可以在自己内部用,必须带类型名
{
println("ERROR")
}
else
{
println("OK")
}
}
}
var a = MyStruct()
a.testStructNumber()// print OK
MyStruct.globalStructNumber = 10
a.testStructNumber()// print ERROR