存储属性
特点
- 存储在类,结构体里的变量或者常量,有两种:实例存储属性和类型存储属性
- 初始值要么在构造器中,要么在就直接赋予,可选类型的存储属性可以不指定初始值
- 系统会提供两个构造器:一个无参数的构造器和一个初始化所有实例存储属性的构造器。
结构体实例存储属性
struct LengthRange {
var start: Int
//定义常量存储属性,可以不指定初始值
let length:Int
}
var len = LengthRange(start:9, length:3)
//通过构造器参数完成实例存储属性的初始化
print("len的起点为\(len.start),长度为\(len.length)")
len.start = 2
//len.length = 4 //这个会报错,因为是常量,常量是不能修改的
计算属性
语法
[修饰符]var计算属性名:属性类型{
get{
//get方法执行体,该方法一定要有返回值
}
set(形参名){
setter方法执行体,该方法一定不能有返回值
}
}
例子1
class User{
var first:String = ""
var last:String = ""
//定义计算属性
var fullName:String{
//定义计算属性的getter方法,该方法的返回值由first,last两个存储属性决定
get{
return first + "-" + last
}
//定义计算属性的setter方法
//该setter方法将负责改变该实例的first,last两个存储属性
set(newValue){
var names = newValue.componentsSeparatedByString("-")
self.first = names[0]
self.last = names [1]
}
}
init(first:String, last:String){
self.first = first
self.last = last
}
}
let s = User(first:"极客",last:"Hello")
//print(s.fullName) //结果是:极客-Hello
s.fullName = "极客-学院"
print(s.first) //outcome is 极客
print(s.last) //结果是 学院
例子2 只读属性
无需set部分,可以省略get和花括号
class User{
var first:String = ""
var last:String = ""
//定义计算属性
var fullName:String{
//定义计算属性的getter方法,该方法的返回值由first,last两个存储属性决定
return first + "-" + last
}
init(first:String, last:String){
self.first = first
self.last = last
}
}
属性观察者
语法
[修饰符]var 计算属性名:属性类型 = 初始值 {
willSet (newValue){
//属性即将被赋值之前自动调用的方法
}
didSet(oldValue){
//属性被赋值完成之后自动调用的方法
}
}
- 除了延迟存储属性之外的所有存储属性(包括实例存储属性和类型存储属性)
- 可通过重载方式为继承得到的属性(包括存储属性和计算属性)添加属性观察者。
例子
class Person {
//定义存储属性
var name: String = ""{
willSet{
if(newValue.characters.count > 6 || newValue.characters.count < 2){
print("您设置的人名\(newValue)不符合要求,请重新设置!")
}else{
print("人名设置符合要求,设置成功")
}
}
didSet{
print("人名设置完成,被修改的原名为:\(oldValue)")
}
}
var age: Int = 0{
willSet{
if newValue > 100 || newValue < 0{
print("您设置的年龄\(newValue)不符合要求,请重新设置!")
}else{
print("年龄设置符合要求,设置成功")
}
}
didSet {
print("年龄设置完成,被修改的年龄为:\(oldValue)")
}
}
}
var p = Person()
//p.age = 999 //不成功的设置,先调用willSet,再调用didSet
p.age = 10 // 成功的设置
print("成功设置年龄后,年龄为\(p.age)")
方法
类型方法:枚举,结构体中方法使用static修饰,类中用class修饰,否则的话属于实例方法
将方法转换为函数
class SomeClass {
func test() {
print("==test 方法==")
}
class func bar(msg:String) {
print("==bar类型方法==,传入的参数为:\(msg)")
}
}
var sc = SomeClass() //创建实例
var f1:()->()=sc.test //将sc的test方法分离成函数
var f2:(String) -> Void = SomeClass.bar //将sc的bar方法分离成函数,定义一个函数型的变量并赋值
//f1() //等价于sc.test()
f2("极客") //等价于SomeClass.bar(msg:"Geek")
方法形参名省略用 “_”
默认除第一个参数外都添加了外部参数名,与局部参数名一样,如果不需要的话,则用_下划线的方式去掉
class Person {
var name:String
init(name:String){
self.name = name
}
func eat (food:String, _ drink:String, cigarette:String){
print("\(self.name)吃着\(food),喝着\(drink),抽着\(cigarette)")
}
}
var p = Person(name:"Tom")
p.eat("烤鸭","啤酒",cigarette:"雪茄")
值类型的可变方法可以改变存储属性
struct JKRect {
var x: Int
var y: Int
var width:Int
var height:Int
mutating func moveByX(x:Int,y:Int){
self.x += x
self.y += y
}
}
var rect = JKRect(x:20, y:12, width:200, height:300) //创建实例
rect.moveByX(100, y:90) //调用mutating方法,该方法可以改变rect实例的存储属性
print("rect矩形的左上角的x坐标为:\(rect.x),y坐标为:\(rect.y)")
- 将mutating关键字放在func之前,即将该方法声明为可变方法
- 常量类型的结构体,枚举是不可变的,比如上述的var 改成 let就不行了
属性和方法的统一
使用函数类型定义存储属性,并将函数或者闭包作为该属性的初始值,这个属性就成了方法
func factorial(n:Int) -> Int {
var result = 1
for i in 1...n {
result *= i
}
return result
}
struct SomeStruct {
var info:() -> Void = {
print("info方法")
}
//将全局函数作为fact存储属性的初始值
static var fact:(Int) -> Int = factorial
}
var sc = SomeStruct()
//调用info方法
//sc.info() //outcome is info方法
//使用闭包对sc对象的info赋值,相当于重新定义sc的info方法
sc.info = {
print("另外一个闭包")
}
//sc.info() //outcome is 另外一个闭包
var n = 6
//调用fact方法,执行的是阶乘
//print("\(n)的阶乘是:\(SomeStruct.fact(6))") //Outcome is 720
//使用闭包对SomeStruct的fact赋值,相当于重新定义SomeStruct的fact方法
SomeStruct.fact = {
var result = 1
for i in 1...$0 {
result += i
}
return result
}
//再次调用fact方法,执行的是累加
print("\(n)的累加的和是:\(SomeStruct.fact(6))") //outcome is 22
下标
- 所有的Swift类型(枚举,类,结构体)都支持定义下标
- 同一个类型可以定义多个下标,通过下标的形参列表或者返回值类型来区分不同的下标
- 同一类型中定义多个不同的下标被称为下标重载
- 形参列表:与函数的形参列表的用法基本相同,但是不支持指定外部参数和默认值
- 下标的返回值类型:可以是任何有效的类型
1 | Subscripe(形参列表) ->下标返回值类型 { |
struct JKRect2{
var x:Int
var y:Int
var width:Int
var height:Int
//定义下标,指定下标只接受一个Int类型的参数,下标的返回类型为Int
subscript(index:Int) ->Int {
get{
switch(index){
case 0:
return self.x
case 1:
return self.y
case 2:
return self.width
case 3:
return self.height
default:
print("不支持该索引值")
return 0
}
}
set{
switch(index){
case 0:
self.x = newValue
case 1:
self.y = newValue
case 2:
self.width = newValue
case 3:
self.height = newValue
default:
print("不支持该索引值")
}
}
}
}
//创建实例
var rect2 = JKRect2(x:20,y:12,width:200,height:300)
//通过下标进行赋值
//rect2[0] = 40
//rect2[1] = 67
//通过下标访问rect的属性
print("rect2矩形的左上角的x坐标为:\(rect2[0]),y坐标为:\(rect2[1])")