我有许多包裹Builder
结构的结构。这些包装器提供了对此Builder
的专门行为。在这些包装器之间进行转换应该很容易,因为它们基本上只是具有专门方法的Builder
。我已经编写了一些代码来说明 - 对于一些简单的东西来说,似乎有很多样板。还有更好的方法吗?
struct Builder;
trait ObjectBuilder: Into<Builder> + From<Builder> {
fn from_other<T: ObjectBuilder>(x: T) -> Self {
let builder = x.into();
builder.into()
}
}
struct OtherBuilder {
inner: Builder
}
impl From<Builder> for OtherBuilder {
fn from(x: Builder) -> OtherBuilder {
OtherBuilder {
inner: x
}
}
}
impl Into<Builder> for OtherBuilder {
fn into(self) -> Builder {
self.inner
}
}
struct OtherOtherBuilder {
inner: Builder
}
impl From<Builder> for OtherOtherBuilder {
fn from(x: Builder) -> OtherOtherBuilder {
OtherOtherBuilder {
inner: x
}
}
}
impl Into<Builder> for OtherOtherBuilder {
fn into(self) -> Builder {
self.inner
}
}
impl ObjectBuilder for OtherBuilder {}
impl ObjectBuilder for OtherOtherBuilder {}
fn main() {
let x = Builder;
let y: OtherBuilder = x.into();
let z: OtherOtherBuilder = ObjectBuilder::from_other(y);
let y = OtherBuilder::from_other(z);
}
答案 0 :(得分:2)
您可以定义Builder
的扩展特征,而不是定义包装器结构,即仅在Builder
上实现的特性,它提供可以使用方法调用语法调用的其他函数({{1而不是builder.func()
)。然后,您只能导入与适当范围相关的特征(无论是模块范围,功能范围等)。
这种方法的一个缺点是,如果你有多个特性提供具有相同名称的方法,那么使用方法调用语法调用这些方法将是不明确的(如果在相关范围中导入了多个线程),作为编译器我不知道你指的是哪种特质。当然,您可以使用普通函数语法(func(builder)
)消除调用的歧义,但这并不漂亮。在这种情况下,也许包装器是一种更好的方法。
答案 1 :(得分:2)
您可以使用宏来减少代码中的重复:
struct Builder;
trait ObjectBuilder: Into<Builder> + From<Builder> {
fn from_other<T: ObjectBuilder>(x: T) -> Self {
let builder = x.into();
builder.into()
}
}
macro_rules! builder {
($name:ident) => {
struct $name {
inner: Builder
}
impl From<Builder> for $name {
fn from(x: Builder) -> $name {
$name {
inner: x
}
}
}
impl Into<Builder> for $name {
fn into(self) -> Builder {
self.inner
}
}
impl ObjectBuilder for $name {}
}
}
builder!(OtherBuilder);
builder!(OtherOtherBuilder);
fn main() {
let x = Builder;
let y: OtherBuilder = x.into();
let z: OtherOtherBuilder = ObjectBuilder::from_other(y);
let y = OtherBuilder::from_other(z);
}