Class 是否有一个“问题”;deleter";在D区?

Class 是否有一个“问题”;deleter";在D区?,class,properties,d,getter-setter,Class,Properties,D,Getter Setter,有没有一种方法可以在D中实现deleter?我找不到任何关于那件事的参考资料。在下面的示例中,我想使用deleter将internal的值重置回其原始状态。如果没有像deleter这样的东西,那么实现上述要求的首选惯用方法是什么?(如果是这样,我也对设计选择感兴趣,为什么这种类型的属性函数不是语言的一部分?) 更新: 基于下面的对话:我给出了一个虚拟示例,这让我们想到,我正在寻找的这种机制可以通过简单的setter和使用属性的.init值轻松实现。但事实并非如此。如果这个属性基本上只是几个函数

有没有一种方法可以在D中实现deleter?我找不到任何关于那件事的参考资料。在下面的示例中,我想使用deleter将
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();*/}