D 是否存在与Ruby';s属性存取器
在Ruby中,我可以轻松地设置类的读/写属性,如下所示:D 是否存在与Ruby';s属性存取器,d,D,在Ruby中,我可以轻松地设置类的读/写属性,如下所示: class Bar attr_accessor :foo, :bizz, :buzz end 这将与 class Bar def foo @foo end def foo=(foo) @foo = foo end def bizz @foo end def bizz=(bizz) @bizz = bizz end def buzz @buzz e
class Bar
attr_accessor :foo, :bizz, :buzz
end
这将与
class Bar
def foo
@foo
end
def foo=(foo)
@foo = foo
end
def bizz
@foo
end
def bizz=(bizz)
@bizz = bizz
end
def buzz
@buzz
end
def buzz=(buzz)
@buzz = buzz
end
end
同样的代码是D,非常冗长,我发现自己到处都在重复:
class Bar {
private {
string _foo, _bizz, _buzz;
}
@property {
string foo() { return _foo; }
string bizz() { return _bizz; }
string buzz() { return _buzz; }
void foo(string foo) { _foo = foo; }
void bizz(string bizz) { _bizz = bizz; }
void buzz(string buzz) { _buzz = buzz; }
}
}
有没有简捷的方法可以做到这一点?是:
public string foo;
在我看来,琐碎的属性访问器是浪费时间的。Ruby强迫您这样做,但D不这么做
如果仍然需要它们,则mixin模板可以执行以下操作:
mixin template attr_accessor(Type, string name) {
static string codeGenerationHelper() {
string code;
// the variable
code ~= "private Type _" ~ name ~ ";";
// the getter
code ~= "public @property Type " ~ name ~ "() { return _" ~ name ~ "; }";
// the setter
code ~= "public @property Type " ~ name ~ "(Type a) { return _" ~ name ~ " = a; }";
return code;
}
mixin(codeGenerationHelper());
}
// here's how to use it
class Foo {
mixin attr_accessor!(string, "foo");
}
void main() {
auto foo = new Foo();
foo.foo = "test";
}
你能给我解释一下
codeGenerationHelper()
位吗?是的,你要做的就是把D代码构建成一个大字符串。然后,下面的mixin表达式告诉编译器将代码粘贴到这里并编译所有代码。所以在这里,我们考虑了代码的样子:一个变量定义,一个getter,然后是setter函数。所以我们在这个helper函数中所做的就是构建那个字符串。D中的~
运算符是string append/concat。我们经常分解字符串以插入变量的名称。否则,语法看起来可能比引号更难,但它只是粘贴在一起的纯D代码。是的,您可以分别执行attr_reader和attr_writer,但需要注意不要两次声明变量。在我的示例中,我在生成的代码字符串中声明了私有变量。这应该只做一次,所以其他两个属性需要处理这个问题。实际上,可能会有,但通常你会使用static if(is(Type==some_-Type_-name)){/*在这里做点什么*/}
,然后else static if(其他东西)
等等。是的,它可以使用反射来检查类中是否存在变量,但这太复杂了,无法在注释中解释。。。