有没有"删除"在D?

时间:2017-08-28 11:16:25

标签: class properties d getter-setter

有没有办法在D中实现删除?我找不到任何引用。在以下示例中,我想使用删除器internal的值重置为其原始状态。如果没有 deleter 这样的东西,那么实现上述要求的首选和惯用方法是什么? (如果是这种情况,我也对设计选择感兴趣,为什么这种类型的属性函数不属于语言?)

class Class
{
    private uint internal = 0;

    @property uint value()
    {
        return this.internal;
    }

    @property uint value(uint input)
    {
        return this.internal = input;
    }
}

更新

基于下面的对话:我给出了一个虚拟的例子,这让我们想到,我正在寻找的这种机制可以通过一个简单的 setter 轻松实现。属性的.init值。然而事实并非如此。如果这个属性基本上只是几个函数调用的方便包装器怎么办?就像一些重置语义相关状态的C函数调用一样 - 这正是我的情况。

为了进一步澄清,我们讨论的是Python所具有的类似机制,它支持 getter setter deleter 。< / p>

2 个答案:

答案 0 :(得分:2)

由于我之前从未听说过删除,我最初回答的问题与提出的问题有些不同。 D没有像Python的删除器那样的东西,下面的建议不能被称为惯用语,但它的功能基本相同,看起来有些相似。

请注意,这会导致可空类型的非直观行为 - a.value = null;将调用特殊删除函数,而a.value = cast(Foo*)null;将调用常规setter。所以你可能根本就不应该这样做。

更为惯用的方法是,要么设置单独的clearValue()功能,要么在将值设置为“已删除”时进行自动清理。值(无效,0或其他)。

class Class
{
    private uint internal = 0;

    @property uint value()
    {
        return this.internal;
    }

    @property uint value(uint input)
    {
        return this.internal = input;
    }

    // deleter
    @property uint value(typeof(null) input)
    {
        DoSpecialCleanup();
        return this.internal = internal.init;
    }
}

unittest
{
    auto c = new Class();
    c.value = 13;
    assert(c.value == 13);
    c.value = null; // Calling deleter here.
    assert(c.value == 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);
}

答案 1 :(得分:2)

简而言之 - no ,D中没有 deleter (一个Python).Python中的删除主要是因为Python的动态性

Python3示例:

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...

在上面这个简单的例子中,显然会员&#34;变量&#34; &#39; someval&#39;是动态创建的(在Python中,这些只是字典中的键......)因此可以使用 del Python关键字轻松取消/销毁。

在D中,由于显而易见的原因,这是不可能的 - 在D中,您无法动态取消设置属性! - 只要对象存在,所有成员都存在。 D的属性机制(非常简单但有效)不提供删除器 - 只有getter和setter可用,这一切都有意义......