[D语言] DMD 0.168发布

本文介绍了D语言的一些新特性,包括为委托增加ptr属性以指向绑定对象,为内嵌类实例增加outer属性以引用外层对象,以及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();
    }
}

这种方式也不是我们所希望的,一般来说委托绑定到多个对象时,因为是取到某成员函数指针,再进行绑定。比如模拟一个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);
}

是的,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;
}

这个特性可能应用并不是很广吧。

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;
}

这些析构函数会和mixin相反的顺序执行。我不明白的是,为什么不让mixin多个构造函数?为何不让这些构造函数晚于被mixin的类(上面的C类)的构造函数,并按mixin进来的顺序执行?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值