Class 是否有一个“问题”;deleter";在D区?
有没有一种方法可以在D中实现deleter?我找不到任何关于那件事的参考资料。在下面的示例中,我想使用deleter将Class 是否有一个“问题”;deleter";在D区?,class,properties,d,getter-setter,Class,Properties,D,Getter Setter,有没有一种方法可以在D中实现deleter?我找不到任何关于那件事的参考资料。在下面的示例中,我想使用deleter将internal的值重置回其原始状态。如果没有像deleter这样的东西,那么实现上述要求的首选惯用方法是什么?(如果是这样,我也对设计选择感兴趣,为什么这种类型的属性函数不是语言的一部分?) 更新: 基于下面的对话:我给出了一个虚拟示例,这让我们想到,我正在寻找的这种机制可以通过简单的setter和使用属性的.init值轻松实现。但事实并非如此。如果这个属性基本上只是几个函数
internal
的值重置回其原始状态。如果没有像deleter这样的东西,那么实现上述要求的首选惯用方法是什么?(如果是这样,我也对设计选择感兴趣,为什么这种类型的属性函数不是语言的一部分?)
更新: 基于下面的对话:我给出了一个虚拟示例,这让我们想到,我正在寻找的这种机制可以通过简单的setter和使用属性的
.init
值轻松实现。但事实并非如此。如果这个属性基本上只是几个函数调用的一个方便的包装器呢?就像两个重置语义相关状态的C函数调用一样——这正是我的情况
为了进一步澄清,我们正在讨论Python具有的类似机制,它支持getter、setter和deleter。因为我以前从未听说过deleter,所以我最初回答的问题与所问的有所不同。D没有任何类似Python的deleters的东西,下面的建议也不能称为惯用,但它基本上做了相同的事情,看起来有些相似 请注意,这将导致可空类型的非直观行为-
a.value=null
将调用特殊的deleter函数,而a.value=cast(Foo*)null
将调用常规setter。所以你可能根本不应该这么做
更惯用的方法是使用一个单独的clearValue()
函数,或者在将值设置为其“已删除”值(为null、0或其他值)时进行自动清理
在我最初(错误地)理解这个问题时,我认为这意味着将所有字段重置为其初始值。这可以通过以下代码完成:
import std.traits;
void reset(T)(auto ref T t) if (is(T == Unqual!T)) {
static if (is(T == class)) {
auto data = T.classinfo.initializer[0..$];
foreach (e; FieldNameTuple!T) {
alias FieldType = typeof(__traits(getMember, T, e));
enum offset = __traits(getMember, T, e).offsetof;
static if (is(FieldType == Unqual!FieldType)) {
__traits(getMember, t, e) = *cast(FieldType*)data[offset..$];
}
}
} else static if (!is(typeof(t = T.init))) {
foreach (e; FieldNameTuple!T) {
alias FieldType = typeof(__traits(getMember, T, e));
static if (is(FieldType == Unqual!FieldType)) {
__traits(getMember, t, e) = __traits(getMember, T.init, e);
}
}
} else {
t = T.init;
}
}
class Bar {
align(16):
int n = 3;
const int n2 = 19;
}
struct Baz {
align(16):
int n = 3;
const int n2 = 19;
}
unittest {
Bar b = new Bar();
b.n = 14;
reset(b);
assert(b.n == 3);
Baz b2;
b2.n = 14;
reset(b2);
assert(b2.n == 3);
}
因为我以前从未听说过删除器,所以我最初回答的问题与所问的有些不同。D没有任何类似Python的deleters的东西,下面的建议也不能称为惯用,但它基本上做了相同的事情,看起来有些相似 请注意,这将导致可空类型的非直观行为-
a.value=null
将调用特殊的deleter函数,而a.value=cast(Foo*)null
将调用常规setter。所以你可能根本不应该这么做
更惯用的方法是使用一个单独的clearValue()
函数,或者在将值设置为其“已删除”值(为null、0或其他值)时进行自动清理
在我最初(错误地)理解这个问题时,我认为这意味着将所有字段重置为其初始值。这可以通过以下代码完成:
import std.traits;
void reset(T)(auto ref T t) if (is(T == Unqual!T)) {
static if (is(T == class)) {
auto data = T.classinfo.initializer[0..$];
foreach (e; FieldNameTuple!T) {
alias FieldType = typeof(__traits(getMember, T, e));
enum offset = __traits(getMember, T, e).offsetof;
static if (is(FieldType == Unqual!FieldType)) {
__traits(getMember, t, e) = *cast(FieldType*)data[offset..$];
}
}
} else static if (!is(typeof(t = T.init))) {
foreach (e; FieldNameTuple!T) {
alias FieldType = typeof(__traits(getMember, T, e));
static if (is(FieldType == Unqual!FieldType)) {
__traits(getMember, t, e) = __traits(getMember, T.init, e);
}
}
} else {
t = T.init;
}
}
class Bar {
align(16):
int n = 3;
const int n2 = 19;
}
struct Baz {
align(16):
int n = 3;
const int n2 = 19;
}
unittest {
Bar b = new Bar();
b.n = 14;
reset(b);
assert(b.n == 3);
Baz b2;
b2.n = 14;
reset(b2);
assert(b2.n == 3);
}
简而言之-不,D中没有deleter(一种Python)。Python中的deleter的存在主要是因为Python的动态特性
Python 3示例:
class MyType():
"""Demonstrates the use of the *deleter* ...
"""
def __init__(self):
self._someval = None
@property
def someval(self):
return self._someval
@someval.setter
def someval(self, value):
self._someval = value
@someval.deleter
def someval(self):
print('someval about to be deleted')
del self._someval
if __name__ == '__main__':
obj = MyType()
obj.someval = 42
print(obj.someval)
del obj.someval # we trigger the deleter here
print(obj.someval) # AttributeError thrown...
在上面这个简单的示例中,很明显,成员“variable”'someval'是动态创建的(在Python中,这些都只是字典中的键…),因此可以很容易地用del Python关键字取消设置/销毁
在D中,这是不可能的,原因很明显-在D中,您不能动态取消设置属性!-只要对象存在,所有成员都存在。D的属性机制(非常简单,但有效)没有提供删除器-只有getter和setter可用,这一切都是有意义的…简言之-不,D中没有deleter(一个la Python)。Python中的删除器的存在主要是因为Python的动态特性
Python 3示例:
class MyType():
"""Demonstrates the use of the *deleter* ...
"""
def __init__(self):
self._someval = None
@property
def someval(self):
return self._someval
@someval.setter
def someval(self, value):
self._someval = value
@someval.deleter
def someval(self):
print('someval about to be deleted')
del self._someval
if __name__ == '__main__':
obj = MyType()
obj.someval = 42
print(obj.someval)
del obj.someval # we trigger the deleter here
print(obj.someval) # AttributeError thrown...
在上面这个简单的示例中,很明显,成员“variable”'someval'是动态创建的(在Python中,这些都只是字典中的键…),因此可以很容易地用del Python关键字取消设置/销毁
在D中,这是不可能的,原因很明显-在D中,您不能动态取消设置属性!-只要对象存在,所有成员都存在。D的属性机制(非常简单,但有效)没有提供删除器-只有getter和setter可用,这一切都是有意义的…什么是删除器
void reset(){internal=0;}
?显然Python有这个概念。差不多就是这样。@BioTronic你把我弄糊涂了一点——这是不一样的!我给了你一个虚拟的例子,这让我们找到了一个虚拟的解决方案。如果此属性基本上是围绕多个函数的方便包装器,该怎么办?(就像大量重置语义相关状态reset的C函数调用一样——这正是我的情况)它们有些相同,但不完全相同。D对于这个特殊的设定器没有特殊的概念。如果确实需要,可以使用@property uint value(typeof(null)input){/*Cleanup();*/}
并在该函数中执行特殊清理<代码>a.value=null代码>将调用此特殊重载。我从来没有见过这样的用法,所以我不能确切地说它是惯用的。正如我在这里所解释的,一种更为惯用的方法可能是clearValue()
函数void reset(){internal=0;}
?显然Python有这个概念。差不多就是这样。@BioTronic你把我弄糊涂了一点——这是不一样的!我给了你一个虚拟的例子,这让我们找到了一个虚拟的解决方案。如果此属性基本上是围绕多个函数的方便包装器,该怎么办?(就像大量重置语义相关状态reset的C函数调用一样——这正是我的情况)它们有些相同,但不完全相同。D对于这个特殊的设定器没有特殊的概念。如果确实需要,可以使用@property uint value(typeof(null)input){/*Cleanup();*/}