由于在Rust中缺乏继承,我偶然发现了一个有点古怪的情况。
我正在设计一个元素结构,其中所有元素都有某些共同的行为(例如,有 child )并且需要在树上传播函数调用。
我当前的设计是具有View
特性和一个封装所有常见行为的ViewInner
结构。但是,这样做似乎会产生大量的样板代码,从而将调用从View
转发到其ViewInner
。并且看起来,添加另一级别的封装(例如AutoLayoutView
)将使调用深度增加三倍。
这是一个简短的示例:
// "Base" view trait
pub trait View {
fn render(&self, ...);
fn handle_events(&self, ...);
}
// View internals
pub struct ViewInner {
children: Vec<Box<View>>
}
impl ViewInner {
...
pub fn add_child(...);
pub fn layout(...);
}
// Forwarded calls
impl View for ViewInner {
fn render(&self, ...) {
for child in self.children.iter() {
child.render(...);
}
}
fn handle_events(&self, ...) {
for child in self.children.iter() {
child.handle_events(...);
}
}
}
// Actual entity
pub struct SomeView {
inner: ViewInner,
...
}
impl SomeView {
pub fn new() -> Self {
return Self {
inner: ViewInner::new()
}
}
}
impl View for SomeView {
// Forwarding all over again
fn render(&self, ...) {
self.inner.render(...)
}
fn handle_events(&self, ...) {
self.inner.handle_events(...)
}
}
在将来(在更多的爬网调用和
View
变体的情况下),构造此结构并最小化样板的最佳方法是什么?
最佳答案
对于在没有任何附加逻辑的情况下转接调用的一般情况,您可以为View特性编写custom derive macro。
有了它,您只需要编写:
#[derive(View)]
pub struct ViewInner {
...
}
并且View特性会自动为该结构实现。
关于oop - 在Rust中设计UI元素树结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61718187/