d结构子类化按命名工作
obj.addText(
ForegroundColor.blue, TextFormat.underline,"链接",
ForegroundColor.black, ~TextFormat.underline,"普通"
);
它通过变参
模板和诸如ForegroundColor
和BackgroundColor
等的各种特化arsd.color
的通用Color
结构的特定子类型
来实现该点.下面为前景色
的源码
.
struct ForegroundColor {
Color color;alias color this;
this(Color c) {
color = c;
}
this(int r, int g, int b, int a = 255) {
color = Color(r, g, b, a);
}
static ForegroundColor opDispatch(string s)() if(__traits(compiles, ForegroundColor(mixin("Color." ~ s)))) {
return ForegroundColor(mixin("Color." ~ s));
}
}
如果重复代码
太多,可用mixin template
.
这里不必在使用点上写ForegroundColor(Color(r,g,b,a))
.
opDispatch
简洁地转发静态方法
给Color
上相同方法,从而允许,如ForegroundColor.white
而不是ForegroundColor(Color.white)
的调用.
别名本
只是转发现有对象
上未知
方法给成员
,并当对象请求子成员
类型时也会转发.即,它允许外部成员
隐式转换为环境需要
的内部
成员.
"现有对象"
是因为,在别名本
生效前,必须已创建该对象.即不能用别名本
来转发构造器
,也不能调用对象
时隐式构造
void foo(ForegroundColor color) {}
Color color;
foo(color);
不会编译.别名本
并不构造.
有了别名本
,期望Color
的函数都可带ForegroundColor
,(编译器自动重写func(fg)
为func(fg.color))
,并且Color
上其他
成员也可通过ForegroundColor
来访问.如,r,g,b
和a
成员将是透明可用
的.
但是,传递给模板
时,模板仍按ForegroundColor
,而不是Color
对待!类似地,函数可在ForegroundColor
而不是在Color
上单独重载
(只要类型
是静态已知
的.与类不同,Color
上无(ForegroundColor)
动态强制转换.记住,编译器重写
为成员
访问.因而,该函数
只看到成员
,而不知道谁持有它.).
由于函数可在编译时
区分差异,可用反省
!看看addText
.
忽略细节,只看函数
的大概:
void addText(Args...)(Args args) {
foreach(arg; args) {
static if(is(typeof(arg)==Something)){
} else static if /* ... */ {
}
}
}
可用foreach
遍历变参(也叫元组
或AliasSeq
),并单独检查
每个参数类型
并响应.
addText
结合分析
类型及检查值,来确定操作.如果看到简单风格,则会打开它.用~
来翻转.如果看到Color
的特化,它会用该类型
来了解它是否
应更改前景或其他颜色值
.
还可在opAssign
或其他属性
中用此模式
,来根据赋值
类型操作.
也可重载函数
来完成它,但循环
更易处理更多组合
.
void addText(ForegroundColor color, string text) {}
void addText(BackgroundColor color, string text) {}
void addText(ForegroundColor color, BackgroundColor bg, string text) {}
void addText(ForegroundColor color, BackgroundColor bg, TextFormat fmt, string text) {}
void addText(string text);
...
//仍用静断
使用循环或重载
,可用相同模式
可模拟命名参数
.为特定
数据片定义特定类型
,可强制调用点
使用该名
,从而提供类型安全
命名参数文档.用重载或循环
,可按任意顺序
使用它们,包括必需的,可选的或默认值
.
struct Size { int w; int h; }
struct Point { int x; int y; }
struct PointUpperLeft { Point p; alias p this; this(int x, int y) { p = Point(x, y); } }
struct PointLowerRight { Point p; alias p this; this(int x, int y) { p = Point(x, y); } }
drawRectangle(Point(0, 0), Size(10, 10), ForegroundColor.red);
drawRectangle(PointUpperLeft(0, 0), PointLowerRight(10, 10), ForegroundColor.red);
drawRectangle(0, 0, 10, 10, 255, 0, 0);
//这是啥意思?
为各种名字
编写结构
需要少量工作,尽管使用插件模板
可大部分自动化,但,对用户
好处是显著
的.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现