在学习这种新的迷人语言时,我编写了这段代码,输出0到10乘以3:
pub struct Multiplier {
factor : int,
current : int
}
impl Multiplier {
pub fn new(factor : int) -> Multiplier {
Multiplier {
factor: factor,
current: 0
}
}
}
impl Iterator<int> for Multiplier {
fn next(&mut self) -> Option<int> {
if self.current > 10 {
None
}
else {
let current = self.current;
self.current += 1;
Some(current * self.factor)
}
}
}
struct Holder {
x : Multiplier
}
impl Holder {
pub fn new(factor : int) -> Holder {
Holder {
x : Multiplier::new(factor)
}
}
fn get_iterator(&self) -> Multiplier {
self.x
}
}
fn main() {
let mut three_multiplier = Holder::new(3).get_iterator();
for item in three_multiplier {
println!("{}", item);
}
}
如果我从此
更改Holder
struct Holder {
x : Multiplier
}
到此:
struct Holder {
x : Iterator<int>
}
我收到了编译警告:
<anon>:27:9: 27:22 error: explicit lifetime bound required
<anon>:27 x : Iterator<int>
^~~~~~~~~~~~~
有人可以解释为什么更改字段类型需要明确的生命周期吗?我知道如何标记生命周期,但我不确定编译器为什么要我这样做。
答案 0 :(得分:3)
您可以通过以下方式添加生命周期:
struct Holder<'a> {
x: Iterator<int>+'a
}
但是请注意,Holder
结构是 unsized ,因为它包含一个未标注的特征对象。这严重限制了您可以对类型执行的操作:例如,您无法直接返回Holder
。
您可以通过Holder
接受类型参数来解决此问题:
struct Holder<T> where T: Iterator<int> {
x : T
}
让我们更改get_iterator
以使用类型参数:
impl<T> Holder<T> where T: Iterator<int>+Copy {
fn get_iterator(&self) -> T {
self.x
}
}
注意:我在此处添加了Copy
,因为get_iterator
当前返回了副本。您可以通过get_iterator
代替&T
来避免约束。
对于new
,您必须完全重新设计它。如果我们保持原样,如果我们将其称为Holder::new
,则编译器会给出错误,因为Holder
现在有一个类型参数,并且编译器无法推断类型,因为new
没有&#39}。使用任何。为了解决这个问题,我们可以通过使用特征提供构造函数来使new
泛型:
trait FactorCtor {
fn new(factor: int) -> Self;
}
然后更改new
以使用该特征:
impl<T> Holder<T> where T: Iterator<int>+FactorCtor {
pub fn new(factor : int) -> Holder<T> {
Holder {
x : FactorCtor::new(factor)
}
}
}
因为我们在此程序中只有FactorCtor
的一个实现,所以编译器在调用T
时设法推断Holder::new
。如果我们添加另一个实现,例如Adder
:
pub struct Adder {
factor : int,
current : int
}
impl FactorCtor for Adder {
fn new(factor: int) -> Adder {
Adder {
factor: factor,
current: 0
}
}
}
impl Iterator<int> for Adder {
fn next(&mut self) -> Option<int> {
if self.current > 10 {
None
}
else {
let current = self.current;
self.current += 1;
Some(current + self.factor)
}
}
}
然后我们得到一个编译器错误:
<anon>:72:9: 72:29 error: unable to infer enough type information about `_`; type annotations required
<anon>:72 let mut three_multiplier = Holder::new(3).get_iterator();
^~~~~~~~~~~~~~~~~~~~
我们可以通过明确指定T
来解决此问题:
fn main() {
let mut three_multiplier = Holder::<Multiplier>::new(3).get_iterator();
for item in three_multiplier {
println!("{}", item);
}
}