如何为一个直到运行时才知道通用特征类型的变量赋值?

问题描述 投票:0回答:1

提前道歉,这可能是一个微不足道的问题,但我什至不知道要寻找答案。我想读取可能经过或未经过 zip 压缩的文件。根据文件扩展名,我需要从简单的

Reader
或从
io::File
创建
BGZFReader<File>
Reader
会对任何实现
Read+Seek
的东西感到满意。非工作代码应该如下所示:

let file_reader = if filename.as_ref().extension().unwrap_or_default() == "gz"
    {   
        let in_file = BGZFReader::new(File::open(filename)?)?;
        Reader::new(in_file)
    }
    else
    {
        let in_file = File::open(filename)?;
        Reader::new(in_file)
    };

但是这当然行不通,因为

Reader<File>
Reader<BGZFReader<File>>
不一样。有没有办法说我的变量
file_reader
可以是
Reader
的任何实例,无论我使用的
Read+Seek
的具体实现是什么?

我想一般性地定义

file_reader
的原因是因为我需要打开多个文件然后传递给下游代码。每个都可以压缩或不压缩,因此为所有可能的组合编写
if/else
语句很快就会变得难以管理。

rust traits
1个回答
0
投票

感谢评论中的提示,我想出了这个解决方案:

trait ReadAndSeek: Read+Seek {}
impl <R: Read+Seek> ReadAndSeek for R {}

fn open_file<P: AsRef<Path> + Debug>(path: P) -> Result<Reader<Box<dyn ReadAndSeek>>>
{
    if path.as_ref().extension().unwrap_or_default() == "gz"
    {
        let in_file = BGZFReader::new(File::open(path)?)?;
        Ok(Reader::new(Box::new(in_file)))
    }
    else
    {
        let in_file = File::open(path)?;
        Ok(Reader::new(Box::new(in_file)))
    }
}

和下游:

let read_file = open_file(read_bed)?;
let coord_file = open_file(coord_bed)?;

let processor = Processor::new(read_file, coord_file)?;

我最初不明白的两件事是:

  1. 创建复合特征,如此处
  2. 所述
  3. Box
    使用具有
    dyn
    特征的内部文件读取器
© www.soinside.com 2019 - 2024. All rights reserved.