#generics #types #rust #enums #overloading
#дженерики #типы #Ржавчина #перечисления #перегрузка
Вопрос:
Предположим, у нас есть следующее перечисление:
#[derive(Serialize)]
#[serde(untagged)]
pub enum CustomType {
Foo(Foo),
Bar(Bar),
}
Для того, чтобы иметь функцию, которая ведет себя одинаково для разных типов параметров:
fn my_function(my_param: amp;CustomType){
// logic to use "my_param"
// my_param is used for the handlebars crate, therefore requires to be Serde Serializable
let source = // ...
handlebars.render_template(amp;source, my_param).unwrap();
}
И мы хотим вызвать такую функцию в разных частях нашей программы следующим образом:
fn function_a(bar: amp;Bar){
my_function(CustomType::Bar(bar.clone()));
}
fn function_b(foo: amp;Foo){
my_function(CustomType::Foo(foo.clone()));
}
Этот код работает, но мне это действительно не нравится, так как я должен .clone()
. Я уже пытался передать только ссылку, но это не сработает для перечисления.
Это правильный способ сделать это в Rust?
Ответ №1:
Вы можете создавать CustomType
ссылки на использование вместо принадлежащих значений, если вы не хотите вызывать clone
:
use serde::{Serialize};
#[derive(Serialize)]
struct Foo(String);
#[derive(Serialize)]
struct Bar(String);
#[derive(Serialize)]
#[serde(untagged)]
enum CustomType<'a> {
Foo(amp;'a Foo),
Bar(amp;'a Bar),
}
fn my_function(my_param: amp;CustomType) {
println!("serialized {}", serde_json::to_string(amp;my_param).unwrap());
}
fn func_foo(foo: amp;Foo) {
my_function(amp;CustomType::Foo(foo));
}
fn func_bar(bar: amp;Bar) {
my_function(amp;CustomType::Bar(bar));
}
fn main() {
let foo = Foo("Foo".to_string());
let bar = Bar("Bar".to_string());
func_foo(amp;foo);
func_bar(amp;bar);
}
Однако, если CustomType
существует единственная причина, по которой вы можете передавать Serializable
типы, my_function
тогда, вероятно, было бы проще просто создать my_function
generic и принимать любые Serializable
ссылки:
use serde::{Serialize};
#[derive(Serialize)]
struct Foo(String);
#[derive(Serialize)]
struct Bar(String);
fn my_function<T: Serialize>(my_param: amp;T) {
println!("serialized {}", serde_json::to_string(my_param).unwrap());
}
fn main() {
let foo = Foo("Foo".to_string());
let bar = Bar("Bar".to_string());
my_function(amp;foo);
my_function(amp;bar);
}
Комментарии:
1. Да! Причина
CustomType
была именно для этой цели. Я не знал, что вы можете просто<T: Serialize>
набивать (я пробовал<T>
раньше, но остановился, поскольку он не был сериализуемым)