繁体   English   中英

为D中的const和非const结构提供@property

[英]Provide @property for const and non-const structures in D

我用这种方式定义一个简单的结构:

struct Person{
    private string _name;

    @property ref string name() { return _name; }
}

@property注释非常酷,但我不知道应该如何正确使用它。

以上是相当不错的,但是我无法将Person传递给需要in Person的函数,例如:

void fun(in Person p) { ... } 

为了避免复制Person我必须使用ref声明参数,尽管我不修改它。

那么如何将属性语法与const-correctness结合起来呢?


编辑:要跟进,可以同样适用于循环吗?

void fun(in Person[] people) {
    foreach(Person p; people) { ... }
}

现在我不想复制人,但我不能使用ref Person因为它是const。 所以我必须在循环中编写ref const(Person) p ,它变成了loong。

通常,你会做什么

@property string name() const { return _name; }
@property void name(string value) { _name = value; }

你不会打扰ref (当然,对于一个string ,没有太多意义)。 对于要避免复制的更复杂类型,可以通过const ref返回,例如

@property ref const(Foo) foo() const { return _foo; }
@property void foo(Foo value) { _foo = value; }

可以重载二传手,使其接受ref Foo除了Foo ,但没有多大意义,因为你会复制传递Foo将它指定_foo反正。

如果你真的想要,你可以通过ref从getter返回并重载它,例如

@property ref const(Foo) foo() const { return _foo; }
@property ref Foo foo() { _foo; }

在这种情况下,非const重载可以用作setter,但是如果你要这样做,为什么还要使用属性呢? 此时,您可能只需将成员变量设为public,因为该属性根本不保护它。 通过返回非const ref ,您已经失去了对成员变量设置方式的控制,并且已经有效地将其作为公共成员变量公开,除了您有额外的函数管道。 它给你的唯一好处是你可以在返回之前做一些事情,并且在调用属性时将调用类型的不变量(如果有的话)(而不会使用公共成员变量),但因为变量可以在没有你控制的情况下设置,与简单地将成员变量公开的简单性相比,这些好处具有可疑的价值。

所以,一般来说,第一个例子是要走的路,偶尔,第二个例子是更好的,但是与第三个例子相比,它可能毫无意义。

编辑:

正如Kozzi11指出的那样 ,你可以实现第三个例子

@property auto ref foo() inout { return _foo; }

要么

@property ref inout(Foo) foo() inout { return _foo; }

而不是有两个函数,但我对它的观点并不比公共成员变量更好。

编辑2:关于你对问题的编辑...

如果你想避免在循环中复制,你必须明确表示类型。

foreach(p; people) { ... }

会工作,但它会复制每个Person因为它迭代people

foreach(ref Person p; people) { ...}

要么

foreach(ref const(Person) p; people) { ...}

将避免复制每个Person

那这个呢:

import std.stdio;

void someFun(in Person person) {
    writeln(person.name);
}

struct Person {
    private string _name;
    @property auto ref name() inout { return _name; }
}

void main(string[] args)
{
    auto person = Person("Osoba Nova");
    someFun(person);
    stdin.readln;
}

编辑:for循环你可以省略类型

void fun(in Person[] people) {
    foreach (p; people) {
        writeln(p.name);
    }
}

属性函数只是一个函数,所以你可以重载它。

@property ref const(string) name() const { return name_; }
@property ref string name() { return name_; }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM