新特性:
1、给委托增加ptr属性,指向委托所绑定的对象。
这是一个语法糖,dg.ptr被转化为cast(void*)dg,它只能作右值,所以除了能读取它以外,在语法上禁止对它赋值。要想把委托绑定到不同的对象,你只能自己实现:
这种方式也不是我们所希望的,一般来说委托绑定到多个对象时,因为是取到某成员函数指针,再进行绑定。比如模拟一个ActiveSupport所扩展的一个ruby.Array#map用法:
是的,delegate内部保存了2个指针,所以我们可以容易地hack它。
[注:上面的main函数中数组直接量赋给栈对象也是这个版本中新增的内容,显然只能用于static对象是很鸡肋的。这里简单带过不提。]
[注:上面这个map的模拟并不是ActiveSupport的map扩展的全部用途,那个map还是收集返回值,这里只演示调用语法。ActiveSupport中扩展的map调用语法是map(&:to_s),就可以收集到数组中所有元素调用to_s后的返回值。]
2、给内嵌内的实例增加outer属性,指向外层对象。
这个特性可能应用并不是很广吧。
3、mixin多个析构函数。
这些析构函数会和mixin相反的顺序执行。我不明白的是,为什么不让mixin多个构造函数?为何不让这些构造函数晚于被mixin的类(上面的C类)的构造函数,并按mixin进来的顺序执行?
1、给委托增加ptr属性,指向委托所绑定的对象。
这是一个语法糖,dg.ptr被转化为cast(void*)dg,它只能作右值,所以除了能读取它以外,在语法上禁止对它赋值。要想把委托绑定到不同的对象,你只能自己实现:
class
Foo{
int foo;
public :
this ( int foo){
this .foo = foo;
}
void bar(){
writefln(foo);
}
}
void main(){
alias void delegate () DG;
DG dg = & ( new Foo( 1 )).bar;
Foo[ 10 ] foos;
foreach ( int i, inout Foo foo; foos){
foo = new Foo(i);
}
void ** ptr = cast( void ** ) & dg;
foreach (Foo foo; foos){
* ptr = cast( void * )foo;
dg();
}
}
int foo;
public :
this ( int foo){
this .foo = foo;
}
void bar(){
writefln(foo);
}
}
void main(){
alias void delegate () DG;
DG dg = & ( new Foo( 1 )).bar;
Foo[ 10 ] foos;
foreach ( int i, inout Foo foo; foos){
foo = new Foo(i);
}
void ** ptr = cast( void ** ) & dg;
foreach (Foo foo; foos){
* ptr = cast( void * )foo;
dg();
}
}
这种方式也不是我们所希望的,一般来说委托绑定到多个对象时,因为是取到某成员函数指针,再进行绑定。比如模拟一个ActiveSupport所扩展的一个ruby.Array#map用法:
import std.stdio;
class Foo{
int foo;
public :
this ( int foo){
this .foo = foo;
}
void bar(){
writefln(foo);
}
}
class Array(T){
private :
T[] data;
public :
this (T[] data){
this .data = data[ 0 .. length];
}
void map( void function() func){
void delegate () dg;
void ** funcPtr = cast( void ** ) & dg + 1 ;
* funcPtr = func;
void ** ptr = cast( void ** ) & dg;
foreach (T v; data){
* ptr = cast( void * )v;
dg();
}
}
}
void main(){
auto arr = new Array ! (Foo)([ new Foo( 1 ), new Foo( 2 ), new Foo( 3 )]);
arr.map( & Foo.bar);
}
class Foo{
int foo;
public :
this ( int foo){
this .foo = foo;
}
void bar(){
writefln(foo);
}
}
class Array(T){
private :
T[] data;
public :
this (T[] data){
this .data = data[ 0 .. length];
}
void map( void function() func){
void delegate () dg;
void ** funcPtr = cast( void ** ) & dg + 1 ;
* funcPtr = func;
void ** ptr = cast( void ** ) & dg;
foreach (T v; data){
* ptr = cast( void * )v;
dg();
}
}
}
void main(){
auto arr = new Array ! (Foo)([ new Foo( 1 ), new Foo( 2 ), new Foo( 3 )]);
arr.map( & Foo.bar);
}
是的,delegate内部保存了2个指针,所以我们可以容易地hack它。
[注:上面的main函数中数组直接量赋给栈对象也是这个版本中新增的内容,显然只能用于static对象是很鸡肋的。这里简单带过不提。]
[注:上面这个map的模拟并不是ActiveSupport的map扩展的全部用途,那个map还是收集返回值,这里只演示调用语法。ActiveSupport中扩展的map调用语法是map(&:to_s),就可以收集到数组中所有元素调用to_s后的返回值。]
2、给内嵌内的实例增加outer属性,指向外层对象。
import std.stdio;
class Outer{
class Inner{}
this (){
Inner inner = new Inner;
inner.outer.foo();
}
void foo(){
writefln( " foo " );
}
}
void main(){
Outer outer = new Outer;
}
class Outer{
class Inner{}
this (){
Inner inner = new Inner;
inner.outer.foo();
}
void foo(){
writefln( " foo " );
}
}
void main(){
Outer outer = new Outer;
}
这个特性可能应用并不是很广吧。
3、mixin多个析构函数。
template A(){
this (){
}
~ this (){
writefln( " A::~A() " );
}
}
template B(){
~ this (){
writefln( " B::~B() " );
}
}
class C{
mixin A;
mixin B;
}
void main(){
C c = new C;
delete c;
}
this (){
}
~ this (){
writefln( " A::~A() " );
}
}
template B(){
~ this (){
writefln( " B::~B() " );
}
}
class C{
mixin A;
mixin B;
}
void main(){
C c = new C;
delete c;
}
这些析构函数会和mixin相反的顺序执行。我不明白的是,为什么不让mixin多个构造函数?为何不让这些构造函数晚于被mixin的类(上面的C类)的构造函数,并按mixin进来的顺序执行?