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
时,程序崩溃
.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现