d定义转串
原文
提示是WebFreak的贡献.感谢他们写这篇文章!
有很多方法可自定义toString方法.方法不完全是D的一部分,而是Phobos中的约定:
用.to!string时,会如下:
1,对象到串的转换调用对象的toString,如果对象为null,则返回"null"串.
2,如,覆盖Object.toString
3,如果根据std.format.write准则定义,则结构到串的转换调用结构的toString方法.
来自std.format.write文档:
聚集类型可定义各种toString函数.如果此函数带FormatSpec或以格式串为参数,则该函数决定接受哪些格式符.
toString应有以下签名之一:
void toString(Writer, Char)(ref Writer w, const ref FormatSpec!Char fmt)
void toString(Writer)(ref Writer w)
string toString();
其中,Writer是接受符(第一个版本的符类型)的输出区间.Writer不必调用模板类型.
有时无法用模板,如toString覆盖Object.toString时.此时,可用以下(较慢且不灵活)函数:
void toString(void delegate(const(char)[]) sink, const ref FormatSpec!char fmt);
void toString(void delegate(const(char)[]) sink, string fmt);
void toString(void delegate(const(char)[]) sink);
多个toString版本可用时,有Writer的版本优先级大于接收器版本.toString()的串版本优先级最低.
现在在结构中定义toString的最简单方法如下:
string toString() const @safe {
import std.conv : text;
// 如用文本, format!"", 或普通连接:
return text(fieldA, ", ", fieldB, ", ", etc);
也可用toString(Writer)(ref Writerw)接口,但我不建议,因为在那犯的错误(如输入函数或编译错误操作),使.to!string和格式(format)不再用该函数,使它无用.
但是,可结合二者:
string toString() const @safe {
import std.array : appender;
auto ret = appender!string;
this.toString(ret);
return ret.data;
}
void toString(W)(ref W writer) const @safe {
writer.put(fieldA);
writer.put(", ");
writer.put(fieldB);
writer.put(", ");
writer.put(etc);
}
还可基于回调/接收器方法重载来覆盖串:
void toString(void delegate(const(char)[]) sink)
{
sink(fieldA);
sink(", ");
sink(fieldB);
sink(", ");
sink(etc);
}
缺点是,不能按@safe,nothrow,pure,等标记接收器.也不能限制接收器复制属性.但是,可在此抓编译器错误,因此比仅用基于Writer方法要好.
定义Writer的toString方法,及用appender!string调用writer的toString很可靠,可抓大多数错误,如果确实无法编译奇怪的writer类型,也可回退到用追加器.
未来可改进writer重载调用.不应检查
__traits(compiles, ...)
//或
is(typeof(...))
而应,检查是否有给定签名方法,然后试调用它.(也许需要无需试编译,就可查看是否有潜在匹配的函数重载的一些特征?)
浙公网安备 33010602011771号