我正在制作一个特性,它将从各种文件格式读取/解码到某个对象。该特征具有内部读者对象的通用std::io::Read
类。我正在尝试创建一个方便的from_filename
构造函数,它将打开文件并使用它。但是我似乎无法使其发挥作用。
这是代码:
use std::io::Read;
use std::fs;
use std::path::Path;
trait MyObjectReader {
type R: Read;
fn new(Self::R) -> Self;
fn from_filename(filename: &str) -> Self where Self: Sized {
let open_file = fs::File::open(&Path::new(filename)).unwrap();
Self::new(open_file)
}
// other methods will go here
}
然后我收到了这个错误:
rustc 1.15.1 (021bd294c 2017-02-08)
error[E0308]: mismatched types
--> <anon>:14:19
|
14 | Self::new(open_file)
| ^^^^^^^^^ expected associated type, found struct `std::fs::File`
|
= note: expected type `<Self as MyObjectReader>::R`
= note: found type `std::fs::File`
我知道.unwrap()
在库中低于标准,我稍后会更改。
我无法理解此错误,因为std::fs::File
没有实现std::io::Read
?在我看来它应该有用。
答案 0 :(得分:3)
没有
hello
实施std::fs::File
?
是。但考虑一下你的特质的实现:
std::io::Read
问题在于impl MyObjectReader for SomeReaderImpl {
type R = AnythingYouLike;
// .. etc
}
可能为R
,但可能不是。{/ p>
您的默认实现是假设File
是R
,所以也许该实现应该放在File
R
的特定实例中}:
File
答案 1 :(得分:1)
通用类型不像接口。边界不是子类。
type R: Read
并不意味着实现Read
的任何类型。它不是一个抽象类。它更像是一个占位符/别名。它意味着实现Read
的一种特定类型。它将在impl
块中定义哪种类型,因此trait
块在那时不知道它。
另一种看待它的方法是,通过说from_filename
返回Self
(任意R: Read
),它必须适用于 {的每个实现{1}},但您的实施只能返回Read
。
答案 2 :(得分:0)
您可能还希望将通用的位置移至new
方法:
use std::io::Read;
use std::fs::File;
trait MyObjectReader {
fn new<R: Read>(R) -> Self;
fn from_filename(filename: &str) -> Self
where Self: Sized
{
let open_file = File::open(&filename).unwrap();
Self::new(open_file)
}
}
这表示new
可以使用实现Read
的任何类型,而不管特征的实现如何定义R
。如果您仍然需要当前未显示的其他方法,则可以将其与关联类型结合使用:
use std::io::Read;
use std::fs::File;
trait MyObjectReader {
type R: Read;
fn new<R2: Read>(R2) -> Self;
fn from_filename(filename: &str) -> Self
where Self: Sized
{
let open_file = File::open(&filename).unwrap();
Self::new(open_file)
}
fn something_else(&self) -> Self::R;
}