您是正确的:
There is no reason for the reference to live as long as the factory, it only needs to live as long as the object the factory is creating (the factory itself doesn’t store a reference to the string).
但是call_phone上的界线却有所不同
fn call_phone>(f: F) { ... }
该代码表明整个工厂只有一个生命周期,将用于每部手机.您想要不同的东西,您想说f是一生中的好工厂:
fn call_phone<... f: for> Factory>(f: F) { ... }
另一个问题是在工厂特征定义中:
trait Factory {
fn new_phone(&self, ms: &'a str) -> P;
}
P的生存期与ms没有关系.特质定义允许返回的电话超过该字符串,对于iPhone实现,绝对应该禁止该字符串!因此,要解决此问题,我们向Phone trait添加了生命周期参数:
trait Phone {
fn call(&self);
}
但是仍然存在一个问题.我们真的不能写那个签名:
fn call_phone Factory>(f: F) { ... }
因为我们希望P不是类型,而是一个类型族(更确切地说,是寿命→类型构造函数).请记住,电话在每次循环迭代中都有不同的类型(因为生存期是类型的一部分,并且不同循环迭代中的生存期是不同的).
计划在将来的Rust中表达这种签名的能力,但是就目前而言,我们必须采取一种变通方法,并将与电话相关的Factory trait类型设置为:
trait Phone {
fn call(&self);
}
struct IPhone {
my_str: &'a str
}
impl Phone for IPhone {
fn call(&self) {
println!("{}", self.my_str);
}
}
trait Factory {
type Output: Phone;
fn new_phone(&self, ms: &'a str) -> Self::Output;
}
struct IPhoneFactory;
impl Factory for IPhoneFactory {
type Output = IPhone;
fn new_phone(&self, ms: &'a str) -> IPhone {
IPhone {
my_str: ms
}
}
}
fn call_phone Factory>(f: F) {
for i in 0..10 {
let s = i.to_string();
let p = f.new_phone(&s);
p.call();
}
}
fn main() {
call_phone(IPhoneFactory);
}
关联类型使工厂只能生产一种产品,这也许就是您想要的.如果希望Factory的不同实现具有不同的输出,则可以使用幻像类型实现此目的:
trait Phone {
type Phantom;
fn call(&self);
}
enum IPhonePhantom {}
struct IPhone {
my_str: &'a str
}
impl Phone for IPhone {
type Phantom = IPhonePhantom;
fn call(&self) {
println!("{}", self.my_str);
}
}
trait Factory {
type Output: Phone;
fn new_phone(&self, ms: &'a str) -> Self::Output;
}
struct MyFactory;
impl Factory for MyFactory {
type Output = IPhone;
fn new_phone(&self, ms: &'a str) -> IPhone {
IPhone {
my_str: ms
}
}
}
fn call_phone Factory>(f: F) {
for i in 0..10 {
let s = i.to_string();
let p = f.new_phone(&s);
p.call();
}
}
fn main() {
call_phone::(MyFactory);
}
“电话”特征上的“幻影”关联类型不是严格必需的,仅需要将电话类型绑定到其幻像类型,并确保“工厂”实现者不会说谎.