rust - 是否可以在 rust 中编写动态的“抽象/共享”特征
问题描述
编辑:
原始问题
在MyTrait
我尝试分享复杂的功能doSth
MyTrait 是为 Foo 实现的。
Foo 有一个内部结构bar
,其类型为T
. 实现应防止为每个T
.
#[derive(Debug)]
pub enum Status{
Open,
Closed,
}
#[derive(Debug)]
pub struct Foo<T>{
name: String,
status: Status,
bar: T
}
#[derive(Debug)]
pub enum SomeError {
Fails,
}
pub trait MyTrait<T> {
type Output;
fn setStatus(&self, status: Status) -> Status;
fn getStatus(&self) -> Status;
fn doSth(&self) -> Result<Self::Output, SomeError>
{
if super::variant_eq(&self.getStatus(), &Status::Closed) {
self.setStatus(Status::Open);
return Ok(T);
};
return Err(SomeError::Fails);
}
}
impl<T> MyTrait<T> for Foo<T> {
type Output = Foo<T>;
fn setStatus(&self, status: Status) -> Status{
self.status = status;
}
fn getStatus(&self) -> Status{
self.status;
}
}
doSth
不编译(其他人可能也没有,它还没有走那么远)
- 预期回报
Result<Self::Output, SomeError>
和实际回报给return Ok(T)
编译器说T is not a value
- 预期回报
Result<Self::Output, SomeError>
和实际回报给return Ok(Self::Output)
编译器说associated item not found in `Self`
- 预期回报
Result<T, SomeError>
和实际回报给return Ok(())
编译器说expected type parameter T, found ()
我确实找到了泛型的示例,共享函数的示例,但没有找到该方法的示例,因此我不确定该方法是否合理。
如果朝着这个方向努力是合理的,那么前进的方向是什么?
解决方案
对于初学者,Status
应该派生PartialEq
以便您可以检查相等性。为 an实现自己的variant_eq
函数enum
几乎总是不正确的方法。
我还建议派生Copy
以便于使用。
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Status {
Open,
Closed,
}
综上所述,这里有一些关于如何使您的代码正确运行的快速评论
pub trait MyTrait<T> {
type Output;
// This set should probably take a mutable reference
fn set_status(&mut self, status: Status);
fn get_status(&self) -> Status;
// You need some way to get output
fn get_output(&mut self) -> Self::Output;
// Now it has everything it needs to work correctly.
fn doSth(&mut self) -> Result<Self::Output, SomeError> {
// Thanks to PartialEq we can use == as normal
if self.getStatus() == Status::Closed {
self.set_status(Status::Open);
// Call function that will be implemented later to provide output
return Ok(self.get_output())
}
// Return is assumed for last line in function
Err(SomeError::Fails)
}
}
即使你不能派生PartialEq
,你至少可以使用一个匹配。
match self.getStatus() {
Status::Closed => {
self.set_status(Status::Open);
Ok(self.get_output())
}
_ => Err(SomeError::Fails),
}
有了这一切,您就可以实现 foo 与您原来的类似。
impl<T> MyTrait<T> for Foo<T> {
type Output = Foo<T>;
// Required mutable reference to work
fn set_status(&mut self, status: Status) {
self.status = status;
}
fn get_status(&self) -> Status {
// ; would have prevented value from being returned
// Status also needs to implement Copy for this to work
self.status
}
fn get_output(&mut self) -> Self::Output {
// Since you have it return an owned value, you need to either clone
// self, or make get_output consume self
self.clone()
}
}
推荐阅读
- video - jitsi meet如何实现负载均衡?
- c# - Chrome 远程桌面 Console.ReadKey 输出 System.ConsoleKey.Packet 而不是击键
- mysql - Laravel 按年和月分组日期
- solr - 如何在 Apache Solr 的文本字段中仅索引文档内容而不是文档属性
- css - 梅反应,我无法正确调整表格宽度
- macos - App Store Connect 页面未加载/太慢
- java - 如何在java中提取html响应的特定文本
- laravel - 如何在 laravel 的 foreach 循环中通过一个提交按钮提交表单?
- vb.net - TicketNumber 的增量
- jenkins - Jenkins 无法保存新项目或无法更新现有项目的配置