D - 纯 类 和结构
D - pure classes and structs
出于好奇,我输入了以下代码:
pure struct Foo{ }
pure class Bar{ }
这显然与 DMD 和 LDC 一起编译。我不知道它做了什么(如果它做了),因为从这样的 structs/classes 调用不纯函数是可以的。那么,将 pure
附加到 class 或结构会发生什么变化?
它没有任何改变。 D 编译器会简单地忽略许多放置在没有意义的位置的关键字。
证明这一点的快速测试:
pure struct S {
static void bar() {}
}
pure unittest {
static assert(!__traits(compiles, S.bar()));
}
一般来说,D 倾向于忽略不适用的属性,如果没有别的,因为通用代码更容易以这种方式编写(有时,它避免了编写一堆静态 ifs 只是以避免将属性应用于它们不会产生任何影响的代码) - 一个示例是您可以将 static
放在模块级别的几乎任何声明上,但它实际上对大多数声明没有任何作用,并且编译器不会抱怨它。
然而,无论出于何种原因,当您标记结构或 class 时,属性的应用方式有点不一致。例如,如果您用 @safe
标记一个结构或 class,那么该结构或 class 中的每个函数都将是 @safe
,除非它被标记为 @trusted
或@system
。相反,如果你用 pure
标记 class 或结构,它什么都不做——就像 static
一样。它只是被忽略了。
我最好的猜测是为什么像 @safe
这样的东西应用于结构或 class 中的所有函数,而像 pure
或 nothrow
这样的属性被忽略的是 @safe
、@trusted
和 @system
可以在结构或 class 中的特定函数上通过在该函数上显式使用不同的属性来撤消,而对于大多数属性,无法反转它们。
然而不幸的是,当 class 或结构不适用或仅适用于 class 或结构中的声明而不适用时,您可以标记带有属性的结构class 或结构本身确实容易让人感到困惑(例如,有些人认为 immutable class C {..}
对 class 意味着一些特殊的东西,而这意味着 [=43= 中的声明] 是 immutable
;这与 class C { immutable { ... } }
没有什么不同)。因此,最终,您必须熟悉每个属性的实际作用,才能知道它们何时实际应用于 class 或结构,何时真正仅应用于 class 或结构内的声明,以及当他们被简单地忽略时。
就个人而言,我从不将属性应用于 class 或结构,除非它们专门用于结构或 class 而不是其中的函数(例如 final
在 class 上意味着与将它放在 class 内的函数上不同的东西),并且实际应用于结构或 class 的属性数量非常少。 static
在某些情况下(只是不在模块级别),abstract
和 final
对 classes 和访问修饰符(public
,private
, 等) 做。根据 TDPL,synchronized
对于 class 也应该是特殊的,但是同步的 classes 从未真正实现过(只是同步函数)。所以,我可能错过了一个,但在我脑海中,这是可以实际应用于结构或 class 的完整属性列表,而所有其他属性要么被忽略,要么应用于其中的声明结构或 class 但不是结构或 class 本身。
出于好奇,我输入了以下代码:
pure struct Foo{ }
pure class Bar{ }
这显然与 DMD 和 LDC 一起编译。我不知道它做了什么(如果它做了),因为从这样的 structs/classes 调用不纯函数是可以的。那么,将 pure
附加到 class 或结构会发生什么变化?
它没有任何改变。 D 编译器会简单地忽略许多放置在没有意义的位置的关键字。
证明这一点的快速测试:
pure struct S {
static void bar() {}
}
pure unittest {
static assert(!__traits(compiles, S.bar()));
}
一般来说,D 倾向于忽略不适用的属性,如果没有别的,因为通用代码更容易以这种方式编写(有时,它避免了编写一堆静态 ifs 只是以避免将属性应用于它们不会产生任何影响的代码) - 一个示例是您可以将 static
放在模块级别的几乎任何声明上,但它实际上对大多数声明没有任何作用,并且编译器不会抱怨它。
然而,无论出于何种原因,当您标记结构或 class 时,属性的应用方式有点不一致。例如,如果您用 @safe
标记一个结构或 class,那么该结构或 class 中的每个函数都将是 @safe
,除非它被标记为 @trusted
或@system
。相反,如果你用 pure
标记 class 或结构,它什么都不做——就像 static
一样。它只是被忽略了。
我最好的猜测是为什么像 @safe
这样的东西应用于结构或 class 中的所有函数,而像 pure
或 nothrow
这样的属性被忽略的是 @safe
、@trusted
和 @system
可以在结构或 class 中的特定函数上通过在该函数上显式使用不同的属性来撤消,而对于大多数属性,无法反转它们。
然而不幸的是,当 class 或结构不适用或仅适用于 class 或结构中的声明而不适用时,您可以标记带有属性的结构class 或结构本身确实容易让人感到困惑(例如,有些人认为 immutable class C {..}
对 class 意味着一些特殊的东西,而这意味着 [=43= 中的声明] 是 immutable
;这与 class C { immutable { ... } }
没有什么不同)。因此,最终,您必须熟悉每个属性的实际作用,才能知道它们何时实际应用于 class 或结构,何时真正仅应用于 class 或结构内的声明,以及当他们被简单地忽略时。
就个人而言,我从不将属性应用于 class 或结构,除非它们专门用于结构或 class 而不是其中的函数(例如 final
在 class 上意味着与将它放在 class 内的函数上不同的东西),并且实际应用于结构或 class 的属性数量非常少。 static
在某些情况下(只是不在模块级别),abstract
和 final
对 classes 和访问修饰符(public
,private
, 等) 做。根据 TDPL,synchronized
对于 class 也应该是特殊的,但是同步的 classes 从未真正实现过(只是同步函数)。所以,我可能错过了一个,但在我脑海中,这是可以实际应用于结构或 class 的完整属性列表,而所有其他属性要么被忽略,要么应用于其中的声明结构或 class 但不是结构或 class 本身。