静态方法
在Swift语言中,Static静态方法属于类型本身,而不是类型的实例。这意味着静态方法在调用时不需要创建特殊的对象实例,它直接与类型关联。
struct Warehouses {
var name: String?
static func getName() -> String {
return "fangjunyu.com"
}
}
struct WarehouseView: View {
var body: some View {
Text(Warehouses.getName())
}
}
与实例方法不同,实例方法需要通过特定的实例调用,因此它们依赖于实例的状态。
struct Warehouses {
var name: String?
func getName() -> String {
return "fangjunyu.com"
}
}
struct WarehouseView: View {
@State private var name = Warehouses()
var body: some View {
Text(name.getName())
}
}
Static静态方法不依赖于对象实例,因此可以直接使用。
案例分析
Static静态方法不需要创建对象实例:
static func getName() -> String {}
这一原因在于我们的静态方法与类型关联,可以在没有实例的情况下使用:
Text(Warehouses.getName())
我们用一个故事来理解一下这里:
比如你独自一人走在村上,遇到朋友问你,你谈女朋友了么?你说还没有。后来,你认识了一个女朋友带回了村里,别人看见了,之后别人就知道你有女朋友了,这看到你的女朋友大概的样貌。再后来,你和你女朋友谈的很好,在村里结婚了,全村认识你的人,都知道你结婚了。
在这个故事中,当别人问你有没有女朋友的时候,就像我们的静态方法需要一个实例,如果那个人没有碰到你,他肯定连问都没有办法问,所以就像没有Static的方法需要一个实例一样,你(实例)来了,别人才可以问你事情。
当你结婚以后,村里放了一天的鞭炮,就好像使用了静态方法。所有人都知道你不仅有女朋友,还结婚了。所以别人在这方面跟你不需要问你,他就知道你已经结婚了,好像所有认识你的人都应该知道一样,也不会多余问你。
因此,没有使用静态方法(结婚或大概都知道事),也没有实例(你没有出去),那么别人就无法调取你的属性或方法(你有没有女朋友的事)。
故事结束。
当你使用静态方法(结婚并全村贴喜字)之后,别人不需要实例就可以直接调取你的属性或方法(知道你有女朋友且结婚了,这里表示知道你结婚的信息)。
我们什么时候使用或不使用静态方法?
使用静态方法的情况:执行与具体实例无关的任务(村里需要统计光棍,计生主任不认识你,但知道你已经结婚了),例如加载默认数据、初始化一些常量(你需要告诉全村人的事情)等等。
什么时候不使用静态情况:当我们的方法需要读取或修改对象实例的时候,就无法使用静态方法.
struct Warehouses {
var name: String?
static func greet() -> String {
return "Hello, \(name)!" // 访问实例属性 name
}
}
在上面的结构中,当我们尝试在greet()方法中使用静态方法时,Xcode会提示我们:
Instance member 'name' cannot be used on type 'Warehouses'
这是因为我们的greet()方法中涉及对象的属性,因为如果想要访问greet(),必须先知道name是什么,才能返回对应的数据。
因此,当涉及到具体上下文时、访问或修改对象属性,或方法的行为依赖于对象的状态或具体数据时,我们就不要使用静态方法。
也可以类比为秒问秒答的游戏,别人问你的每一个问题,你都需要在1秒内作出回答,而比较深层次的问题,就需要你思考后再回答给别人。这里深层次的问题就是涉及到对象的属性(需要你思考),所以你无法马上告诉别人你的答案。
因此,涉及深层次的问题,需要思考(涉及具体上下文时、访问或修改对象属性)时,我们就不能马上回答出来。
延伸问题
在初始化过程当中,可能存在我们调用某个实例状态相关的方法或属性。
struct Warehouses {
var name: String = getName()
func getName() -> String {
return "fangjunyu.com"
}
}
在这段代码中,定义name属性的一行会报错:
Cannot use instance member 'getName' within property initializer; property initializers run before 'self' is available
这个报错为无法在属性初始化程序中使用实例成员”getName”,属性初始化程序需要在self之前使用。
简单的可以理解为,当我们想要创建一个Warehouses结构的实例,首先是name的初始化,在name初始化时,遇到了还没有初始化的getName(),因此就会报错,因为还没有初始化到getName()。
var name: String = getName() // 准确的手表时间
func getName() -> String { // 别人问你时间是多少
return "fangjunyu.com"
}
打个比喻,你是全村里唯一一个有手表的人,在这里我们的手表时间就是name变量,getName()方法就是别人问你现在的时间是多少。
只有我们早上起床、穿衣并带上手表(完全初始化)之后,我们才可以告诉别人现在是几点。
我们也可以把这个时间是几点几分记到脑子里,然后就可以直接告诉别人(使用name属性)。
当我们使用静态方法之后,我们就可以直接给name赋值等于getName()方法:
struct Warehouses {
var name: String = getName()
static func getName() -> String {
return "fangjunyu.com"
}
}
添加上静态方法的变量,就像手表变成了大本钟,所有人都可以直接看到,而不需要再问你了。同时你也可以直接抬头望见大本钟的时间(name = getName()),不需要起床、穿衣并带上手表(完全初始化)。