Non proprio. Quello che ho visto è l'introduzione di una nuova struct
per ciascuna variante enum, e quindi metodi sul enum a decomporsi essa:
struct Dog(i32);
struct Cat(u8);
enum Animal {
Dog(Dog),
Cat(Cat),
}
impl Animal {
fn cat(self) -> Cat {
if let Animal::Cat(c) = self { c } else { panic!("Not a cat") }
}
fn dog(self) -> Dog {
if let Animal::Dog(d) = self { d } else { panic!("Not a dog") }
}
}
// Or better an impl on `Cat` ?
fn count_legs_of_cat(c: Cat) -> u8 {
c.0
}
Naturalmente, non è necessario necessità struct e si poteva solo restituire il u8
, ma potrebbe essere difficile da tracciare.
C'è un barlume di supporto migliore per questo in futuro, tuttavia. I penso è il "efficient code reuse" RFC, ma meglio descritto nel post del blog Virtual Structs Part 3: Bringing Enums and Structs Together. La proposta consisterebbe nel consentire a Animal::Cat
di essere di tipo standalone, pertanto il tuo metodo potrebbe accettare uno Animal::Cat
e non doversi preoccupare di ciò.
Personalmente, ho quasi sempre preferisco scrivere il codice infallibile nella mia implementazione intrinseca e costringere il chiamante al panico:
impl Animal {
fn cat(self) -> Option<Cat> {
if let Animal::Cat(c) = self {
Some(c)
} else {
None
}
}
fn dog(self) -> Option<Dog> {
if let Animal::Dog(d) = self {
Some(d)
} else {
None
}
}
}
E probabilmente userei un match
impl Animal {
fn cat(self) -> Option<Cat> {
match self {
Animal::Cat(c) => Some(c),
_ => None,
}
}
fn dog(self) -> Option<Dog> {
match self {
Animal::Dog(d) => Some(d),
_ => None,
}
}
}
invece di impl Animal tendo a implorare la caratteristica Into, come [questo esempio di playground] (http://is.gd/jmS3RB). Con le enumerazioni semplici dovrebbe essere relativamente facile avere una macro per generare l'impls, ma non è un pattern che uso tanto, quindi non ho mai avuto il tempo di scriverlo ... –