结构方法类型推断

时间:2015-03-08 15:35:14

标签: rust

鉴于以下内容:

use std::old_io::{BufferedReader, File};

struct Journal<T> where T: Buffer {
    file: T,
}

impl<T: Buffer> Iterator for Journal<T> {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        match self.file.read_line() {
            Ok(line) => Some(line.to_string()),
            Err(_) => None,
        }
    }
}

fn main() {
    let path = Path::new("/tmp/allocator-journal.txt");
    let mut file = BufferedReader::new(File::open(&path));

    let journal = Journal {file: file};
    for line in journal {
        print!("{}", line);
    }
}

我想将文件打开逻辑移到Journal上的new方法中。由于unable to infer enough type information about '_'; type annotations required [E0282]

,以下内容无法编译
use std::old_io::{BufferedReader, File, IoResult};

struct Journal<T> where T: Buffer {
    file: T,
}

impl<T: Buffer> Journal<T> {
    fn new() -> Journal<BufferedReader<IoResult<File>>> {
        let path = Path::new("/tmp/allocator-journal.txt");
        let mut file = BufferedReader::new(File::open(&path));
        Journal {file: file}
    }
}

impl<T: Buffer> Iterator for Journal<T> {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        match self.file.read_line() {
            Ok(line) => Some(line.to_string()),
            Err(_) => None,
        }
    }
}

fn main() {
    let journal = Journal::new();
    for line in journal {
        print!("{}", line);
    }
}

无法向变量绑定添加类型提示或方法调用(Journal::new::<Journal<BufferedReader<etc..>>>)都无法解决问题。

为什么不能输入这种类型? Journal :: new的签名是明确的,对吧?

顺便说一句,为什么Journal::new()的返回类型为Journal<T>,其中T =缓冲区?

1 个答案:

答案 0 :(得分:2)

您正在混合仿制药和非仿制药的世界(细节?)。这是修复:

impl Journal<BufferedReader<IoResult<File>>> {
    fn new() -> Journal<BufferedReader<IoResult<File>>> {
        let path = Path::new("/tmp/allocator-journal.txt");
        let mut file = BufferedReader::new(File::open(&path));
        Journal {file: file}
    }
}

请注意此处缺少T。重点是您决定T必须是什么类型(BufferedReader<IoResult<File>>),因此不需要类型变量。

通过拥有类型变量,编译器正试图找出T应该是什么。但是,您不能在任何地方使用T,因此没有任何内容可以连接点,并且您会收到错误说明。

这提出了一个问题:为什么要使用泛型?您实际上并没有将它们用于任何事情,因此您也可以将T替换为BufferedReader<IoResult<File>>无处不在。