2016-09-15 7 views
0

인수를 기반으로 일부 포트를 만들지 만 포트가 다음 함수로 전달되기에 충분히 길지는 않습니다. 더 나은 여전히, 정적으로 파견이 적응하는 방법?녹에서 입력 소스를 전환하는 가장 좋은 방법

fn init<'a>(matches: getopts::Matches) { 
    let in_port: &mut Read = match matches.opt_str("i") { 
     Some(filename) => &mut File::open(filename).expect("Couldn't open input file.") as &mut Read, 
     _ => &mut io::stdin() as &mut Read, 
    }; 
    let out_port: &mut Write = match matches.opt_str("o") { 
     Some(filename) => &mut File::create(filename).expect("Couln't open output file") as &mut Write, 
     _ => &mut io::stdout() as &mut Write, 
    }; 
    run(in_port, out_port); 
} 
+1

이 A''잡다한 것입니다? –

답변

1

당신은 모든 경기의 팔에 직접 run 함수를 호출하여 정적 파견을 사용할 수 있습니다

use std::fs::File; 
use std::io::{Read, Write}; 

fn init(i: Option<&str>, o: Option<&str>) { 
    match i { 
     Some(filename) => init2(File::open(filename).expect("Couldn't open input file."), o), 
     None => init2(std::io::stdin(), o), 
    } 
} 

fn init2<R: Read>(i: R, o: Option<&str>) { 
    match o { 
     Some(filename) => run(i, File::create(filename).expect("Couldn't open output file")), 
     None => run(i, std::io::stdout()), 
    } 
} 

fn run<R: Read, W: Write>(i: R, o: W) { 
    unimplemented!() 
} 
+0

아름답게 일하면서 정적 디스패치를 ​​사용하는 보너스 포인트. 고맙습니다! –

1

은 가장 간단한 솔루션은 힙에 그들을 가하고, Box 당신의 객체가 될 것입니다.

나는 개인적으로 initrun를 분리하는 것을 선호, 그래서 그들을 반환 의미

fn init(matches: Matches) -> (Box<Read>, Box<Write>) { 
    let in_port: Box<Read> = match matches.opt_str("i") { 
     Some(filename) => Box::new(File::open(filename).expect("Couldn't open input file.")), 
     _ => Box::new(stdin()), 
    }; 
    let out_port: Box<Write> = match matches.opt_str("o") { 
     Some(filename) => Box::new(File::create(filename).expect("Couln't open output file")), 
     _ => Box::new(stdout()), 
    }; 
    (in_port, out_port) 
} 
1

문제는 당신이 파괴하려합니다 뭔가에 대한 참조를 반환하려고하는 것입니다 :

let in_port: &mut Read = match matches.opt_str("i") { 
    Some(filename) => &mut File::open(filename).expect("Couldn't open input file.") as &mut Read, 
    _ => &mut io::stdin() as &mut Read, 
}; 

블록 내에서 생성 된 File은 임시로만 표현식이 지속됩니다. 구체적인 유형을 숨길 수 있도록 값보다는 참조를 사용한다고 가정합니다. d 특성 개체. 한 가지 방법은 우리에게 Box<Trait>인데, 이는 객체를 소유하게됩니다.

fn init<'a>(i: Option<&str>, o: Option<&str>) { 
    let mut in_port: Box<Read> = match i { 
     Some(filename) => Box::new(File::open(filename).expect("Couldn't open input file.")), 
     _ => Box::new(io::stdin()), 
    }; 
    let mut out_port: Box<Write> = match o { 
     Some(filename) => Box::new(File::create(filename).expect("Couln't open output file")), 
     _ => Box::new(io::stdout()), 
    }; 
    run(&mut in_port, &mut out_port); 
} 

(playground)