Как вызвать функцию с разными типами?

Предположим, у нас есть следующее перечисление:

#[derive(Serialize)]
#[serde(untagged)]
pub enum CustomType {
    Foo(Foo),
    Bar(Bar),
}

Чтобы иметь функцию, которая ведет себя одинаково для разных типов параметров:

fn my_function(my_param: &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(&source, my_param).unwrap();
}

И мы хотим вызывать такую ​​функцию в разных частях нашей программы следующим образом:

fn function_a(bar: &Bar){
  my_function(CustomType::Bar(bar.clone()));
}

fn function_b(foo: &Foo){
  my_function(CustomType::Foo(foo.clone()));
}

Этот код работает, но мне он очень не нравится, так как приходится .clone(). Я уже пытался передать только ссылку, но для перечисления это не сработает.

Это правильный способ сделать это в Rust?

Как создавать пользовательские общие типы в Python (50/100 дней Python)
Как создавать пользовательские общие типы в Python (50/100 дней Python)
Помимо встроенных типов, модуль типизации в Python предоставляет возможность определения общих типов, что позволяет вам определять типы, которые могут...
0
0
101
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете заставить CustomType брать ссылки вместо собственных значений, если не хотите вызывать clone:

use serde::{Serialize};

#[derive(Serialize)]
struct Foo(String);

#[derive(Serialize)]
struct Bar(String);

#[derive(Serialize)]
#[serde(untagged)]
enum CustomType<'a> {
    Foo(&'a Foo),
    Bar(&'a Bar),
}

fn my_function(my_param: &CustomType) {
    println!("serialized {}", serde_json::to_string(&my_param).unwrap());
}

fn func_foo(foo: &Foo) {
    my_function(&CustomType::Foo(foo));
}

fn func_bar(bar: &Bar) {
    my_function(&CustomType::Bar(bar));
}

fn main() {
    let foo = Foo("Foo".to_string());
    let bar = Bar("Bar".to_string());
    func_foo(&foo);
    func_bar(&bar);
}

детская площадка

Однако, если единственная причина существования CustomType заключается в том, что вы можете передавать Serializable типы в my_function, то, вероятно, было бы проще просто сделать my_function универсальным и принимать любые Serializable ссылки:

use serde::{Serialize};

#[derive(Serialize)]
struct Foo(String);

#[derive(Serialize)]
struct Bar(String);

fn my_function<T: Serialize>(my_param: &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(&foo);
    my_function(&bar);
}

детская площадка

Да! Причина CustomType была именно для этой цели. Я не знал, что вы можете просто <T: Serialize> вещи (я пытался с <T> раньше, но остановился, так как это не было сериализуемым)

Lykos94 25.12.2020 20:27

Другие вопросы по теме