簡體   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