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.initT()不同的.

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时,程序崩溃.

posted @   zjh6  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示