Рабочий код очищает от сахара:
let s = match v4_or_v6 {
IpAddr::V4(ip) => <Ipv4Addr as ToString>::to_string(&ip),
IpAddr::V6(ip) => <Ipv6Addr as ToString>::to_string(&ip),
};
Несмотря на то, что операторы выглядят одинаково, они являются разными функциями, и в каждой ветви статически известно, какой to_string
будет использоваться.Чтобы заставить это работать в одной руке совпадения, вам нужно каким-то образом создать объект черты из сопоставления с образцом, чтобы каждый ip
имел одинаковый тип (то есть &dyn ToString
).В настоящее время нет способа сделать это, и я не видел ни одного подобного предложения.
Довольно часто встречаются одинаково выглядящие спичечные рукава, где для каждого вызывается один и тот же метод черты, даже вrustc
проект.Пока это так.
Если у вас есть enum
, где каждый вариант содержит типы, которые реализуют одинаковые черты, может быть удобно реализовать черты на enum
и делегировать внутренним типам.Если у вас нет признака, но у ваших типов есть общая структура (как в полях x
, y
в структуре вашего обновленного сообщения), тогда вы можете предоставить аксессор на enum
:
impl Record {
fn x(&self) -> i32 {
match self {
Record::V4(Point { x, .. }) => *x,
Record::V6(Point { x, .. }) => *x,
}
}
}
Хотя это в основном одно и то же, это означает, что вы можете написать его один раз, а не везде, к которому вам нужен доступ x
:
let rec = get_record();
let x = get_record().x();
Обратите внимание, что IpAddr
уже делает этоТаким образом, в исходном коде вы могли бы избежать match
вместе с:
let s = v4_or_v6.to_string();