Can we have generic methods inside a dyn trait? (template method pattern)

Hello.

Is there a way to implement the template method pattern for dynamically dispatched traits, or in words, is there a way to have methods in a trait that are allowed to be generic, are required to be implemented, and do not have to be dynamically polymorphic, that is, the methods are not accesses through the virtual table?

Here is an example:

use std::{any::Any, sync::Arc};

trait Hello {
    fn hello(&self) -> Arc<dyn Any + Send + Sync>;

    // Error: the trait `Hello` cannot be made into an object

    // fn hello_template<S: Any + Send + Sync>(&self) -> Arc<S> {
    //     self.hello().downcast::<S>().unwrap()
    // }
}

struct HelloImpl;

impl Hello for HelloImpl {
    fn hello(&self) -> Arc<dyn Any + Send + Sync> {
        println!("Hello!");
        Arc::new(5i32)
    }
}

fn main() {
    let hello: Box<dyn Hello> = Box::new(HelloImpl {});

    let _val: Arc<i32> = hello.hello().downcast::<i32>().unwrap();

    // What I want to be able to do, even though `hello` is a dyn Trait:
    // let _val: Arc<i32> = hello.hello_template();
}

Of course, it is possible to create a separate function taking a reference to the object implementing the trait instead of having the method inside the trait, but having the method would be just a convenient way to logically assign the functions to the trait.

5 Likes

Alternatively, you can define an inherent method on the trait object:

impl dyn Hello + '_ {
    fn hello_template<S:Any+Send+Sync>(&self) -> Arc<S> {
        self.hello().downcast::<S>().unwrap()
    }
}
5 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.