d简化默认构造器
原文
我发现创建只设置给定属性的构造器很烦.如:
class Foo {
int x;
int y;
int z;
this(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
}
对构,它会自动生成构造器,如果对类也可自动生成构造器就更好了,如下:
class Foo {
int x;
int y;
int z;
default this(int x, int y, int z);
}
这只是前者的语法糖.
如果已指定了构造器,对构也可用:
struct Vector3 {
float x;
float y;
float z;
this(Vector2 v) {
x = v.x;
y = v.y;
}
default this(float x, float y, float z);
}
这会避免很多冗余,让事情更简洁.
有个区别.构的默认初化器是每个成员的.init值.T()不是默认构造器,而是等价于T.init的构字面(.a).
类的默认初化器总是null,且没有类字面.
我不反对你的建议,只是指出两者区别.
试试:
class Foo {
int x;
int y;
int z;
// 1个小函数(.a)
this(typeof(this.tupleof) t) {
this.tupleof = t;
}
}
void main() {
auto foo = new Foo(1, 2, 3);
assert(foo.x == 1);
assert(foo.y == 2);
assert(foo.z == 3);
}
在dart中可:
class Point
{
num x;
num y;
Point(this.x, this.y);
}
var p = Point(10.0, 20.0);
哦,这是'tupleof'的有趣用法.我甚至不知道可按左值用它.如果不知道D的内部结构,就不清楚.而且,如果只想初化一个或两个值而不是所有值,这就不管用了,但它仍然是有用的.
你会喜欢withMe()插件模板,示例打印:
//S!(Letter)(ab, [10, 20], true)
auto withMe(string elements, Me, T...)(Me me, T arg){
with(me) mixin(elements);return me;
}
enum { A = 97, B, C, D }
enum a = Letter(A);
enum b = Letter(B);
struct Letter {
char letter = 96;
alias letter this;
}
import std.stdio;
void main()
{
struct S(T)
{
T[] word;
int[] nums;
bool view;
}
auto test = S!Letter().withMe!q{
word = [a, b];
nums = [10, 20];
view = true;
};
test.writeln;
}
可插件.a,且可有默认参数:
mixin template memberAssigningConstructor() {
// 小函数
this(typeof(this.tupleof) t = typeof(this.tupleof).init) {
this.tupleof = t;
}
}
import std.stdio;
class Foo {
int x;
int y;
int z;
mixin memberAssigningConstructor!();
override string toString() const {
import std.format : format;
return format!"%s %s %s"(x, y, z);
}
}
void testWith(Args...)(Args args) {
auto f = new Foo(args);
writeln(f);
}
void main() {
testWith();
testWith(1);
testWith(1, 2);
testWith(1, 2, 3);
}
但是,建议测试编译速度,因为我在大约3年前的一个项目中实现opCmp时使用了插件的tupleof.该用法只有6个实例,但编译时间很长,外部多次导入它.
用普通函数替换tupleof惯用法解决了编译速度问题.
:.a.
差不多.但T是嵌套结构时,T.init及T()是不同的.
void main()
{
int n;
struct S
{
int fun() { return ++n; }
}
auto s1 = S();
assert(s1.fun() == 1); // 好
auto s2 = S.init;
assert(s2.fun() == 2); // 段错误
}
使用S()初化s1的环境指针,会使它运行时指向主栈帧,允许s1.fun访问n变量.而使用S.init初化s2时.会设置环境指针为null,所以调用s2.fun时,程序崩溃.
浙公网安备 33010602011771号