1.实例存储属性与实例变量
2.结构体常量与实例属性
3.定义计算属性
4.setter方法
5.属性观察者
存储属性:存储在类.结构体里的变量或者常量
分为:实例存储属性.类型存储属性
所有的存储属性必须显示的指定初始值,在定义时或者构造器当中指定
可选类型的存储属性可以不指定初始值
结构体中实例存储属性的规则
1.程序为所有的实例存储属性指定了初始值,且没有构造器,则系统会提供两个构造器:一个无参数的构造器和一个初始化所有实例存储属性的构造器
2.没有初始值和构造器,系统会提供一个初始化所有实例存储属性的构造器
3.有构造器,则程序必须为结构体中的所有存储属性提供初始值
struct LengthRange{
var start: Int
// 定义常量存储属性,可以不指定初始值
let length: Int
}
var len = LengthRange(start: 9, length: 3)
// 通过构造器参数完成实例存储属性的初始化
print("len的起点为\(len.start), 长度为\(len.length)")
// 结构体常量与实例属性
struct LengthRange2{
var start: Int
var length: Int
}
let len2 = LengthRange2(start: 1, length: 5)
// 延迟存储属性:第一次被调用时候才会被计算初始值的属性,用lazy修饰符
/*
[修饰符]var 计算属性名: 属性类型{
get{
// get方法执行体,该方法一定要有返回值
}
set(形参名){
// setter方法执行体,该方法一定不能有返回值
}
}
*/
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: "Devin", last: "hello")
print(s.fullName)
s.fullName = "Devin-Hello"
print(s.first)
print(s.last)
// 只读属性,则无需set部分,可以省略get和花括号
1.除了延迟存储属性之外的所有存储属性(包括实例存储属性和类型存储属性)
2.可通过重载方式为继承得到的属性(包括存储属性和计算属性)添加属性观察者
/*
[修饰符]var 计算属性名: 属性类型 = 初始值{
willSet(newValue){
// 属性即将被赋值之前自动调用的方法
}
didSet(oldValue){
// 属性被赋值完成之后自动调用的方法
}
}
注意:willSet和didSet后的参数都可以省略
*/
/*
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 // 不成功设置
// 成功设置age属性后
p.age = 10
print("成功设置age属性后, age为\(p.age)")
1.定义方法需要在类型(枚举.结构体.类)里定义,不能独立定义
2.方法要么属于该类型本身,要么是该类型的一个实例
3.不能独立执行方法,执行方法必须使用类型或实例作为调用者
注意:枚举.结构体中方法使用static修饰,类中用class修饰,都属于类型方法,否则的话属于实例方法
class SomeClass {
func test() {
print("===test 方法===")
}
class func bar(msg msg: String) {
print("==bar类型方法==, 传入的参数为:\(msg)")
}
}
// 创建实例
var sc = SomeClass()
// 将sc的test方法分离成函数
var f1: () -> () = sc.test
// 将sc的bar方法分离成函数
var f2:(String) -> Void = SomeClass.bar
f1() // 等价于sc.test()
sc.test()
f2("Devin") // 等价于SomeClass.bar(msg:"Devin")
SomeClass.bar(msg: "Devin")
class Person1 {
var name: String
//
init(name: String) {
self.name = name
}
//
func eat(food: String, _ drink: String, _ cigarette: String) {
print("\(self.name)吃着\(food), 喝着\(drink), 抽着\(cigarette)")
}
}
var p1 = Person1(name: "Devin")
p1.eat("烤鸭", "啤酒", "雪茄")
// Swift默认为除第一个参数外都添加了外部参数名,与局部参数名一样,如果不需要的话,则用 _ 下划线的方式去掉
将mutating关键字放在func之前,即将该方法声明为可变方法
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)
// 调用mutating方法,该方法可以改变rect实例的存储属性
rect.moveByX(100, y: 90)
print("rect矩形的左上角的x坐标为:\(rect.x), y坐标为:\(rect.y)")
// 注意:常量类型的结构体.枚举是不可变的
使用函数类型定义存储属性,并将函数或者闭包作为该属性的初始值,这个属性就成了方法
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 sc1 = SomeStruct()
// 调用info方法
//sc1.info()
// 使用闭包对sc1对象的info赋值,相当于重新定义sc1的info方法
sc1.info = {
print("另外一个闭包")
}
//sc1.info()
var n = 6
// 调用fact方法,执行的是阶乘
print("\(n)的阶乘是:\(SomeStruct.fact(6))")
// 使用闭包对SomeStruct的fact赋值,相当于重新定义SomeStruct的方法
SomeStruct.fact = {
var result = 1
for i in 1...$0 {
result += i
}
return result
}
// 再次调用fact方法,执行的是累加
print("\(n)的累加的和是:\(SomeStruct.fact(6))")
1.下标的基本用法
2.下标重载
1.所有的Swift类型(枚举.类和结构体)都支持下标定义
2.同一个类型可以定义多个下标
3.通过下标的形参列表或者返回值类型来区分不同的下标
4.同一类型中定义多个不同的下标被称为下标重载
/*
Subscript(形参列表) -> 下标返回值类型 {
get {
// getter方法执行体,该方法必须有返回值
}
set(形参名) {
// setter方法执行体,该方法不能有返回值
}
}
*/
// 1.形参列表:与函数的形参列表的用法基本相同,但是不支持指定外部参数和默认值
// 2.下标的返回值类型:可以是任何有效的类型
struct JKRect2 {
var x: Int
var y: Int
var width: Int
var height: Int
// 定义下标,指定下标只接受一个Int类型的参数,下标的返回类型为Int
subscript(index: Int) -> Int {
// get部分
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部分
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.x), y坐标为:\(rect2.y)")