Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 扩展可能不包含存储属性,但为什么允许静态_Swift_Swift Extensions - Fatal编程技术网

Swift 扩展可能不包含存储属性,但为什么允许静态

Swift 扩展可能不包含存储属性,但为什么允许静态,swift,swift-extensions,Swift,Swift Extensions,扩展不能包含存储属性,但为什么可以在扩展中定义静态存储属性 我也没有发现任何文档提到扩展中允许使用静态属性 extension String { static let test = "Test" static var test2 = "Test2" } 扩展不能包含存储的实例属性。为什么?因为添加实例属性会更改该类型实例的大小。如果一个模块添加一个扩展名,使得Int现在有两个单词长,会发生什么情况?例如,当它从另一个模块获取一个Int,而该模块的大小仍然为1个单词时,会发生什么情况 扩

扩展不能包含存储属性,但为什么可以在扩展中定义静态存储属性

我也没有发现任何文档提到扩展中允许使用静态属性

extension String {
  static let test = "Test"
  static var test2 = "Test2"
}

扩展不能包含存储的实例属性。为什么?因为添加实例属性会更改该类型实例的大小。如果一个模块添加一个扩展名,使得
Int
现在有两个单词长,会发生什么情况?例如,当它从另一个模块获取一个
Int
,而该模块的大小仍然为1个单词时,会发生什么情况

扩展中允许静态存储属性的原因很简单,因为它们具有静态生存期;它们独立于您要扩展的给定类型的任何实例而存在。实际上,它们只不过是全局存储变量,只是命名为一个类型。因此,可以自由添加它们,而不会影响在不知道它们的情况下已编译的代码

但是值得注意的是,目前定义静态存储属性有三个限制

1.不能在泛型类型上定义
静态
存储属性 这将需要对通用占位符的每个单独专业化进行单独的财产存储。例如,使用:

struct S<T> {

    static var foo: Int {
        return 5
    }

    static let bar = "" // error: Static stored properties not supported in generic types
}
如果运行时每次以新的
S
专门化访问
date
时都隐式生成新的存储,则
S.date
将不等于
S.date
;这可能令人困惑和/或不受欢迎

2.不能在协议扩展中定义
静态
存储属性 这主要是从上一点开始的。协议扩展中的
static
存储属性需要为该协议的每种符合类型分别存储(但同样,编译器/运行时没有理由不能这样做)

这对于协议是必需的,因为协议扩展中的
静态
成员不是协议类型本身的成员。它们是符合协议的具体类型上的成员

例如,如果我们有:

protocol P {}

extension P {

    static var foo: Int {
        return 5
    }

    static let bar = "" // error: Static stored properties not supported in generic types
                        // (not really a great diagnostic)
}

struct S : P {}
struct S1 : P {}
我们无法访问协议类型本身的
foo
,我们不能说
p.foo
。我们只能说
S.foo
S1.foo
。这很重要,因为
foo
的getter可以调用
self
上的静态协议需求;但是,如果
self
P.self
(即协议类型本身),这是不可能的

对于
静态
存储的属性,如
,也可能会出现同样的情况

3.不能定义
存储属性 我不相信在类主体本身中这样的声明会有任何问题(它只相当于由
静态
存储属性支持的计算的
属性)


但是,在扩展中可能会出现问题,因为扩展无法将新成员添加到Swift类vtable(尽管它们可以添加到Obj-C对应项(如果适用))。因此,在大多数情况下,它们不会被动态地分派到(因此实际上是
最终的
,因此
静态的
)。尽管如此,
class
computed属性目前在扩展中是允许的,因此为了保持一致性,它可能是允许的。

Hmm。唯一明确指出的是“Swift中的扩展可以:添加计算实例属性和计算类型属性(…)”他们从来没有提到在扩展中允许存储类型属性,所以我一直认为它们是不允许的。顺便问一下,
static var
也同样有效。文档中是否有任何地方指定允许使用static?还是Swift用户必须推断出这一点?@Boon问得好!我找不到任何官方文件说明这一点;但我们可以看一下,它指出“枚举和扩展不能有存储实例属性。允许静态存储属性,但下面强制执行限制。”这些限制适用于1。泛型和2<代码>类存储的属性。可能值得向苹果公司提交一个bug,因为文档中没有提到它。回答得很好。来自
scala
我对这里描述的限制有点失望,因为它们都可以用那种语言轻松处理。但这并不会降低内容的质量。
protocol P {}

extension P {

    static var foo: Int {
        return 5
    }

    static let bar = "" // error: Static stored properties not supported in generic types
                        // (not really a great diagnostic)
}

struct S : P {}
struct S1 : P {}