问题描述
在Java语言中,我有一个interface R
,一个interface RT extends R
(其中RT
实现了所有R
)和一堆其他都实现了RT
的类.
In Java-lingo, I have an interface R
, an interface RT extends R
(where RT
implements all of R
) and a bunch of other classes that all implement RT
.
向Rust的过渡我有两个特征
Transitioning to Rust I ended up with two traits
trait R { ... }
trait RT { ... }
其中RT
是R
的子特征":
impl R for X where X: RT { ... }
接着我有一堆结构,所有这些结构都实现了RT
:
Following that I have a bunch of structs, all of which implement RT
:
struct RV { ... }
impl RT for RV { ... }
struct I { ... }
impl RT for I { ... }
struct U { ... }
impl RT for U { ... }
// ...
到目前为止一切都很好.
So far so good.
现在,我希望所有这些结构在实现全部RT
的基础上彼此具有可比性.
Now I want all of these structs to be comparable to each other, on the basis that all of them implement RT
.
在Java中,我将RT
更改为
In Java I would change RT
to
interface RT extends R, Comparable<RT>
并为equals
和compareTo
添加默认实现.
在Rust中,我不知道是否或如何解决这个问题.
In Rust I have no idea if or how this could be approached.
我可以说trait RT: PartialEq
,但这只会使一个实现与其自身具有可比性(RV == RV
,但不能与RV == U
相比).
I could say trait RT: PartialEq
, but that would only make one implementation comparable with itself (RV == RV
, but not RV == U
).
我的下一个想法是为每个结构添加一揽子实现:
My next idea was to add blanket implementations for every struct:
impl PartialEq<RV> for X where X: RT
impl PartialEq<I> for X where X: RT
// ...
我理解为什么不允许这样做,但是我仍然会遇到最初的问题.
I understand why this isn't allowed, however I'm still stuck with my initial problem.
我无法转换比较值(RV as RT == U as RT
),因为不能将RT
制成对象.
I can't cast the values for comparison (RV as RT == U as RT
) because RT
can't be made into an object.
我可以为每种结构的组合手动实现PartialEq<T>
,但这会造成很多重复.
I could manually implement PartialEq<T>
for every combination of structs but that would be a lot of duplication.
我考虑过使用宏来生成所有不同的实现,但是感觉就像蛮力的,所以我质疑程序的初始设计.
I considered using a macro to generate all the different implementations, but that feels so much like brute-forcing, that I question the initial design of my program.
我如何使所有不同的结构彼此可比?
How do I make all the different structs comparable to each other?
推荐答案
这种模式通常出现在Java中,以模拟带标记的联合,而Java语言中缺少这种联合.在Rust中,除非您编写的库可能需要用户定义RT
的新实现,否则我怀疑您会更喜欢使用enum
而不是特征对象:
That pattern often arises in Java to emulate tagged unions, which are missing from the Java language. In Rust, unless you are writing a library whose users may need to define new implementations of RT
, I suspect you’ll be happier with an enum
instead of a trait object:
#[derive(PartialEq, Eq)]
enum AnyRT {
RV(RV),
I(I),
U(U),
}
impl RT for AnyRT {
fn foo(&self, ...) {
match self {
AnyRT::RV(rv) => rv.foo(...),
AnyRT::I(i) => i.foo(...),
AnyRT::U(u) => u.foo(...),
}
}
}
然后,根据您的应用程序,您可能会发现根本不需要RT
特征和/或单独的RV
,I
,U
结构.
Depending on your application, you may then find that you don’t need the RT
trait and/or the separate RV
, I
, U
structs at all.
这篇关于我该如何使许多不同的结构都实现相同的特征并相互比较?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!