代理模式和隐藏在Rust中的实现?

代理模式和隐藏在Rust中的实现?,rust,Rust,因此,我是一名经验丰富的开发人员,对Rust来说是个新手,Java方面的专家,但我是从汇编语言开始的,所以我获得了内存和分配,并且编写了足够多的编译器y代码,可以很好地理解借用检查器 我决定移植一个非常有用的、基于位集的高性能图形库,这是我用Java编写的,既可以在更大的最终项目中使用,也因为它非常有用。因为它都是位集中的整数位置,如果你想要一个对象图,你可以将索引映射到一个数组或其他什么东西中——我不会纠结于构建一个相互引用的对象巨树,这在Rust中是一个混乱的尝试。我试图解决的问题要简单得多

因此,我是一名经验丰富的开发人员,对Rust来说是个新手,Java方面的专家,但我是从汇编语言开始的,所以我获得了内存和分配,并且编写了足够多的编译器y代码,可以很好地理解借用检查器

我决定移植一个非常有用的、基于位集的高性能图形库,这是我用Java编写的,既可以在更大的最终项目中使用,也因为它非常有用。因为它都是位集中的整数位置,如果你想要一个对象图,你可以将索引映射到一个数组或其他什么东西中——我不会纠结于构建一个相互引用的对象巨树,这在Rust中是一个混乱的尝试。我试图解决的问题要简单得多——如此简单,我觉得我一定缺少了一个明显的模式来解决:

查看各种可用于生锈的位集库,似乎是一个很好的选择然而,我不希望通过我的API公开它,不可撤销地将我库中的每个消费者与FixedBitSet绑定在一起(这很好,但是,交换一个由原子学支持的实现也是有用的;与
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() {
            // ...
        }
    }
}