文件结构不被视为实现读取?

时间:2017-03-11 13:17:33

标签: rust traits

我正在制作一个特性,它将从各种文件格式读取/解码到某个对象。该特征具有内部读者对象的通用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?在我看来它应该有用。

3 个答案:

答案 0 :(得分:3)

  

没有hello实施std::fs::File

是。但考虑一下你的特质的实现:

std::io::Read

问题在于impl MyObjectReader for SomeReaderImpl { type R = AnythingYouLike; // .. etc } 可能R,但可能不是。{/ p>

您的默认实现是假设FileR,所以也许该实现应该放在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;
}