Swift知识扩展:Static静态方法的实际运用
Swift知识扩展:Static静态方法的实际运用

Swift知识扩展:Static静态方法的实际运用

静态方法

在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()),不需要起床、穿衣并带上手表(完全初始化)。

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注