O que esse erro significa?
error[E0308]: mismatched types
--> src/main.rs:50:35
|
50 | PaymentType::InvoiceIn => InvoiceIn {
| ___________________________________^
51 | | name: "Invoice 1".to_string(),
52 | | payed: false,
53 | | },
| |_________^ expected `dyn Payable`, found `InvoiceIn`
|
= note: expected trait object `dyn Payable`
found struct `InvoiceIn`
= help: `InvoiceIn` implements `Payable` so you could box the found value and coerce it to the trait object `Box<dyn Payable>`, you will have to change the expected type as well
For more information about this error, try `rustc --explain E0308`.
Código:
trait Payable {
fn toggle_payed(&mut self);
}
enum PaymentType {
InvoiceOut,
InvoiceIn,
}
struct Payment {
r#type: PaymentType,
}
struct InvoiceOut {
name: String,
payed: bool,
}
impl Payable for InvoiceOut {
fn toggle_payed(&mut self) {
self.payed = !self.payed
}
}
struct InvoiceIn {
name: String,
payed: bool,
}
impl Payable for InvoiceIn {
fn toggle_payed(&mut self) {
self.payed = !self.payed
}
}
fn save_invoice_in(invoice: &InvoiceIn) {
println!("{}", invoice.name)
}
fn save_invoice_out(invoice: &InvoiceOut) {
println!("{}", invoice.name)
}
fn main() {
let payment = Payment {
r#type: PaymentType::InvoiceOut, // This comes from user!
};
let payable: dyn Payable = match payment.r#type {
PaymentType::InvoiceIn => InvoiceIn {
name: "Invoice 1".to_string(),
payed: false,
},
PaymentType::InvoiceOut => InvoiceOut {
name: "Invoice 2".to_string(),
payed: false,
},
};
// Do something else with payable here
payable.toggle_payed();
// Do something else with payable here
match payment.r#type {
PaymentType::InvoiceIn => save_invoice_in(&payable),
PaymentType::InvoiceOut => save_invoice_out(&payable),
};
}
Aqui está uma tentativa de mostrar as duas possibilidades mencionadas nos comentários.
Este exemplo está subdividido em três partes:
std::any::Any
para fazer o downcast para o tipo original,enum
.Em teoria, a solução «dinâmica» poderia estar aberta a muito mais variantes (implementadas noutros locais) do que as que estão presentes na parte «comum», mas como parece precisar de algum tipo de downcasting, não creio que seja realmente atende a sua necessidade.
A solução «enum» parece a melhor para mim, especialmente porque você parece precisar se concentrar em um número finito de variantes (conhecidas de uma vez por todas no enum). Observe que a
enum_dispatch
caixa pode ajudar a encaminhar as chamadas de método através das variantes.