代理模式和隐藏在Rust中的实现?
因此,我是一名经验丰富的开发人员,对Rust来说是个新手,Java方面的专家,但我是从汇编语言开始的,所以我获得了内存和分配,并且编写了足够多的编译器y代码,可以很好地理解借用检查器 我决定移植一个非常有用的、基于位集的高性能图形库,这是我用Java编写的,既可以在更大的最终项目中使用,也因为它非常有用。因为它都是位集中的整数位置,如果你想要一个对象图,你可以将索引映射到一个数组或其他什么东西中——我不会纠结于构建一个相互引用的对象巨树,这在Rust中是一个混乱的尝试。我试图解决的问题要简单得多——如此简单,我觉得我一定缺少了一个明显的模式来解决: 查看各种可用于生锈的位集库,似乎是一个很好的选择然而,我不希望通过我的API公开它,不可撤销地将我库中的每个消费者与FixedBitSet绑定在一起(这很好,但是,交换一个由原子学支持的实现也是有用的;与代理模式和隐藏在Rust中的实现?,rust,Rust,因此,我是一名经验丰富的开发人员,对Rust来说是个新手,Java方面的专家,但我是从汇编语言开始的,所以我获得了内存和分配,并且编写了足够多的编译器y代码,可以很好地理解借用检查器 我决定移植一个非常有用的、基于位集的高性能图形库,这是我用Java编写的,既可以在更大的最终项目中使用,也因为它非常有用。因为它都是位集中的整数位置,如果你想要一个对象图,你可以将索引映射到一个数组或其他什么东西中——我不会纠结于构建一个相互引用的对象巨树,这在Rust中是一个混乱的尝试。我试图解决的问题要简单得多
usize
结合可能并不理想,但FixedBitSet是)
在Java中,您只需创建一个接口来包装具体类型的实例,并公开所需的功能,隐藏实现类型。在Rust中,您有自己的特点,因此很容易实现:
pub trait Bits<'i, S: Sized + Add<S>> {
fn size(&'i self) -> S;
fn contains(&'i self, s: S) -> bool;
...
impl<'i, 'a> Bits<'i, usize> for FixedBitSet {
fn size(&'i self) -> usize {
self.len()
}
fn contains(&'i self, s: usize) -> bool {
FixedBitSet::contains(self, s)
}
...
这是可以实现的:
impl<'a, 'b> Biterable<'a, 'b, usize, Ones<'b>> for FixedBitSet where 'a: 'b {
fn set_bits<'c>(&'a mut self) -> Ones<'b> where Ones<'b>: 'c, 'b: 'c {
self.ones()
}
}
徒劳地搜索编译并工作的东西(这失败了,因为位和可比特化
是特征,显然可比特化+位
不是特征)。说真的-一个无状态的、不需要分配的包装器,用于对这个东西的一次调用,返回对那个东西的一次调用,只是不向调用方公开那个东西的类型。就这样。Java等价物是supplierA=。。。;return()->a.get()代码>
我对这个问题想错了。怎么做?看起来你确实把事情复杂化了。你有很多似乎不必要的终生注释。”这是一个简单的实现(忽略泛型s
):
我强烈反对这种做法,原因有很多。1) 您需要更多的约束,而不仅仅是Add
,才能远程使用。2) 您受到impl位的严重限制
;它没有完全定义,因此不能使用dyn位
或将其存储在结构中。3) 在这方面,我看不出通用性有什么好处。确实看起来你把事情复杂化了。你有很多似乎不必要的终生注释。”这是一个简单的实现(忽略泛型s
):
我强烈反对这种做法,原因有很多。1) 您需要更多的约束,而不仅仅是Add
,才能远程使用。2) 您受到impl位的严重限制
;它没有完全定义,因此不能使用dyn位
或将其存储在结构中。3) 在这方面,我看不出通用性有什么好处。我不会说您一直认为它是错的,只是Rust还没有支持您的用例所需的功能。你可能需要和。我认为用S
参数化Bits
实际上并不能使它更通用。如果您的公共API公开了dyn位
,那么将其更改为例如位
(以支持对不同后端的更改?)无论如何都是向后不兼容的,因此将S
作为参数与将其作为关联类型(例如dyn位
)相比没有明显的优势或者甚至只是像kmdreko的回答那样将其硬编码为usize
。你可能是对的,在这种情况下泛型可能不会添加任何东西-我还没有真正发展出直觉,知道哪些泛型或相关类型适合于给定的情况。顺便说一句,我要澄清我对有生命周期的泛型的评论:如果你有一个指定迭代器类型的特征-trait Foo
,使用fn whatev(&self):I
但是具体的迭代器类型在其类型上指定了一个生存期,似乎除了bitrable
中无用的'b
生存期之外,没有办法干净地处理它,以给返回的具体迭代器一些生存期,而不是'static
。有更好的办法吗?我不确定我是否明白。如果您有一个图形
类型,并且它有一些API方法公开dyn位
或dyn位
,无论您选择哪个,您已经将图形
锚定到usize
。将Graph
的实现从FixedBitSet
更改为FancyBitSet
将是一个突破性的改变,或者您必须将FancyBitSet
包装在同样实现位的东西中,这意味着Bits
在将Graph
的外部API与其内部实现隔离的目标上失败了。我不会说您一直在错误地考虑它,只是Rust还没有支持您的用例所需的功能。你可能需要和。我认为用S
参数化Bits
实际上并不能使它更通用。如果您的公共API公开了dyn位
,那么将其更改为例如位
(以支持对不同后端的更改?)无论如何都是向后不兼容的,因此将S
作为参数与将其作为关联类型(例如dyn位
)相比没有明显的优势或者甚至只是像kmdreko的回答那样将其硬编码为usize
impl<'a, 'b> Biterable<'a, 'b, usize, Ones<'b>> for FixedBitSet where 'a: 'b {
fn set_bits<'c>(&'a mut self) -> Ones<'b> where Ones<'b>: 'c, 'b: 'c {
self.ones()
}
}
impl<'a, 'b, B> Biterable<'a, 'b, usize, &'b mut dyn Iterator<Item=usize>>
for Box<dyn B + 'a> where 'a: 'b, B : Bits<'a, usize> + Biterable<'a, 'b, usize, Ones<'b>> {
use fixedbitset::FixedBitSet; // 0.2.0
pub trait Bits {
fn size(&self) -> usize;
fn contains(&self, s: usize) -> bool;
fn set_bits<'a>(&'a mut self) -> Box<dyn Iterator<Item = usize> + 'a>;
}
impl Bits for FixedBitSet {
fn size(&self) -> usize {
self.len()
}
fn contains(&self, s: usize) -> bool {
self.contains(s)
}
fn set_bits<'a>(&'a mut self) -> Box<dyn Iterator<Item = usize> + 'a> {
Box::new(self.ones())
}
}
pub fn get_bits_from_api() -> impl Bits {
FixedBitSet::with_capacity(64)
}
use fixedbitset::FixedBitSet; // 0.2.0
pub trait Bits {
type Idx: std::ops::Add<Self::Idx>;
fn size(&self) -> Self::Idx;
fn contains(&self, s: Self::Idx) -> bool;
fn set_bits<'a>(&'a self) -> Box<dyn Iterator<Item = Self::Idx> + 'a>;
}
impl Bits for FixedBitSet {
type Idx = usize;
fn size(&self) -> Self::Idx {
self.len()
}
fn contains(&self, s: Self::Idx) -> bool {
self.contains(s)
}
fn set_bits<'a>(&'a self) -> Box<dyn Iterator<Item = Self::Idx> + 'a> {
Box::new(self.ones())
}
}
pub fn get_bits_from_api() -> impl Bits {
// ^^^^^^^^^ doesn't have <Idx = usize>
FixedBitSet::with_capacity(64)
}
fn main() {
let bits = get_bits_from_api();
// just a demonstration that it compiles
let size = bits.size();
if bits.contains(size) {
for indexes in bits.set_bits() {
// ...
}
}
}