扩展不能包含存储的属性,但是为什么可以在扩展内定义静态存储的属性呢?
我也没有找到任何文档提及扩展中允许使用静态属性。
extension String {
static let test = "Test"
static var test2 = "Test2"
}
扩展不能包含存储的 实例 属性。为什么?因为添加实例属性会更改该类型的实例的大小。如果一个模块添加了一个扩展名,使得an
Int
现在为2个字,会发生什么情况?例如,当它Int
从另一个仍为1个字大小的模块中获取一个时,应该怎么办?
扩展中允许使用 静态
存储属性的原因仅仅是因为它们具有静态生存期。它们独立于要扩展的给定类型的任何实例而存在。实际上,它们只不过是全局存储的变量,只是命名空间为一种类型。因此,可以自由添加它们,而不会影响在不了解它们的情况下已经编译的代码。
但是,值得注意的是,当前在定义静态存储属性方面存在三个限制。
static
在通用类型上定义存储的属性对于通用占位符的每个单独的专业化,这将需要单独的属性存储。例如,使用:
struct S<T> {
static var foo: Int {
return 5
}
static let bar = "" // error: Static stored properties not supported in generic types
}
就像foo
对S
,S<Int>.foo
和S<Float>.foo
而 不是
对S
自身进行专门化所要求的一样(实际上;S
目前甚至还不是一种类型,它都需要T
满足)。bar
(可能)是相同的。这将被称为,例如S<Int>.bar
,没有S.bar
。
这是一个重要的细节,因为调用静态成员的元类型将作为隐式self
参数传递给接收者。这可以在静态属性初始化程序表达式中访问;因此允许他们调用其他静态方法。
因此,能够在泛型类型的 不同 专长上调用相同的静态属性初始化程序,就有可能为每个类型创建不同的属性值(考虑的简单情况static let baz = T.self
)。因此,我们需要为它们中的每一个单独存储。
综上所述,没有真正的理由使编译器/运行时无法做到这一点,并且很可能在该语言的未来版本中做到这一点。尽管有一个反对的说法,那就是在某些情况下它可能会产生混乱的行为。
例如,考虑:
import Foundation
struct S<T> {
static let date = Date()
}
如果运行时隐式地产生新的存储date
每次它获取上的一个新的专业化的访问S<T>
,那么S<Float>.date
就不会相等S<Int>.date
;
这可能会造成混淆和/或不期望。
static
在协议扩展中定义存储的属性这主要是从上一点开始的。一个static
在协议扩展存储的属性将需要对每个符合类型的协议单独的存储(但同样的,没有任何理由的编译器/运行时无法做到这一点)。
这对于协议是必要的,因为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
吸气剂可以调用静态协议要求self
;
但是,这是不可能self
的P.self
(即协议类型 本身),因为协议不符合自身。
对于static
存储的属性(例如),也可能会发生同样的情况bar
。
class
存储的属性我不认为类主体中的此类声明会存在任何问题(它等同于class
由static
存储属性支持的计算属性)。
但是,在扩展中可能 会 出现问题,因为扩展无法将新成员添加到Swift类vtable中(尽管可以将它们添加到Obj-C对应对象中)。因此,在大多数情况下,它们不会动态分配给(实际上是final
,因此static
)。尽管如此,但扩展名当前允许使用class
计算 属性,因此出于一致性考虑,可以允许使用 计算 属性。
问题内容: 我想知道Java中是否有特殊原因总是使用“ ”而不是“ ”来定义类型参数的界限。 例: 被禁止但是 是正确的。是什么原因呢? 问题答案: 在类“实现”还是“扩展”之间,通用约束语言没有语义差异。约束可能性是“扩展”和“超级”-也就是说,该类是可分配给其他类的对象(扩展),还是该类可从该类分配(超级)。
问题内容: 我刚接触PHP,但是多年来我一直在使用类似的语言进行编程。我被以下内容弄糊涂了: 它产生了语法错误:这就是调用。 但这很好用: 碰了一会儿之后,我被告知您不能在默认属性中调用函数。你必须在做。我的问题是:为什么?这是“功能”还是草率的实现?有什么根据? 问题答案: 编译器代码建议这是设计使然,尽管我不知道其背后的官方原因是什么。我也不确定要可靠地实现此功能需要花费多少精力,但是目前完成
问题内容: 作为实验,我尝试扩展-array,如下所示: 在类本身中添加一些与排序,交换,子数组构建等有关的方法。但是我在编译时遇到了这个错误: 我很好奇:为什么Java不允许扩展数组? 问题答案: 扩展基本类型(例如a 或数组)会打开安全漏洞。如果Java允许您扩展数组,则采用数组的方法将变得不安全。这就是字符串为,而数组根本不能扩展的原因。 例如,您可以重写该方法,并返回不正确大小的数组。这有
Java说: 所以说数组是协变的。但对于泛型,他们说: 因此它是不变量。但问题是,“泛型真的不变吗?”? 例如,如果我给出: 这意味着列表可以采用异常的子类型,例如这是有效的: 那么为什么泛型被称为不变量呢?
在爪哇,its说: 所以数组被称为协变的。但对于泛型,他们说: 因此它是不变的。但问题是,“泛型真的是不变的吗”? 那为什么说泛型是不变的呢?
问题内容: 我们正在使用SQL Server 2008,其中一项要求是在为系统定义的实体上具有可扩展的用户定义属性。例如,我们可能有一个名为Doctor的实体,我们希望系统管理员能够定义通常不在系统中的其他属性。这些属性很可能是链接父表或联接表的查询条件所必需的。 将有定义属性(名称,描述,类型)等的表,但是我的问题是实际数据值的存储。 我不是DBA(只是一个假装成程序员的DBA),但我首先想到的