d的匿名类
原地址
作者:亚当.
D也有匿名类.
class A {}
A foo() {
return new class A {
override string toString() {
return "匿名!";
}
};
不必给出基类,默认为对象.
Object foo() {
return new class {
// 内容
};
}
你甚至可以实现父和接口:
interface I { int getInt(); }
class Base { string getString() { return "串"; } }
I foo() {
return new class Base, I {
int getInt() { return 15; }
};//基类,实现接口
}
void main() {
import std.stdio;
I i = foo();
writeln(i.getInt());
Base b = cast(Base) i;
writeln(b.getString());
}
很酷,有时可节约你单独写类定义.当然,函数中你也可嵌套类并同样访问局部变量.多种写法.
你可与d的自动返回结合起来,就有了到匿名类型的引用,而不仅是基/接口.
auto foo() {
return new class {
int i;
};
}
为什么很酷呢?因为你可在上面用d的反射.
auto foo() {
return new class {
int i;
};
}
void main() {
auto f = foo();
//显示`i`和自动生成的`本`构造器
pragma(msg, __traits(derivedMembers, typeof(f)));
}
D禁止在表达式环境中声明.因而对反射,匿名类用来传递偶尔用的东西是很方便的.但规范禁止按模板值参发送类对象.所以你得在ctfe端严格或严格按类型来工作.
template some_cool_thing(T) {
pragma(msg, __traits(derivedMembers, T));
}
void main() {
some_cool_thing!(typeof(new class {
int y;
}));//严格按类型
}
typeof(new class { })是合法的,不用单独写名字来聚集声明.但有用吗?..可能!但相比直接单独写声明太冗长了.
总之,可在函数中简单快速匿名分组.也可搞笑的替换元组,但明显是类分配.
对局部变量,你可以scope i = new class {};,这样不必分配.
void main() @nogc {
scope a = new class {
int a = 5;
};
import core.stdc.stdio;
printf("%d\n", a.a);
}
你不能返回它,只能作为局部变量.
dmd -betterC也接收该函数,但由于缺少d运行时而链接失败,但,下面小程序在betterC中工作.
extern(C++) class O {
extern(D)
abstract int omg();
}
extern(C)
int main() @nogc {
scope a = new class O {
int a = 5;
override int omg() { return a; }
};
import core.stdc.stdio;
printf("%d\n", a.a);
return 0;
}
dmd -betterC管用了.我用匿名类来实现com.还可以.很酷,很有用.
类的域覆盖局部域!
class A {
int a;
}
A foo() {
int a;
return new class A {
this() {
//这里,A.a的引用,非上面的`a`.
//this,自赋值
this.a = a; // 不干活
}
};
}
父类,看起来更近,你容易忘记是自己在子类里面,而且编译器不会警告你.
上面是经验,你如何传递本地变量进来呢?匿名类有构造参数吗?
但规范中有,语法很怪,如下:
void main() {
int a = 83;
auto obj = new class (a) {//(a)为构造构造器的参数列表.
this(int a) {
import std.stdio;
writeln("传递进来了", a);
}
};
}
参数列表在基类/接口前,在类关键字后.
new后还可有分配器参数.
一般,你写new Object(args),所以,我试了new class Base(args)/ new class { ... } (args);,但没用.最后查规范找到.注意,D有模板参数.
总之,这样,本地变量与类成员不会冲突.
小技巧
你可在模板声明前放用定属.
@foo module whatever;
import module_with_foo;
导入不能放在模块声明前,但仍可用后面导入的符号.
当前,模块声明中仅允许用定属和过时.
浙公网安备 33010602011771号