How to return an instance of a trait?

二次信任 提交于 2020-01-06 15:09:50

问题


I'm working on a SQL migration tool. Right now I only support Postgresql but i'd like to add Mysql, etc.

I have the following trait that drivers need to implement:

pub trait Driver {
    fn ensure_migration_table_exists(&self);
    fn remove_migration_table(&self);
    fn get_current_number(&self) -> i32;
    fn set_current_number(&self, number: i32);
    fn migrate(&self, migration: String, number: i32) -> MigrateResult<()>;
}

I want to make a function get_driver which would have the following conceptual definition fn get_driver(url: &str) -> MigrateResult<Driver>.

Based on a discussion on IRC a month ago, this is apparently impossible to do. My previous best guess fails like so:

fn get_driver<T: Driver + Sized>(url: &str) -> MigrateResult<T>

expected `core::result::Result<T, errors::MigrateError>`,
found `core::result::Result<drivers::pg::Postgres, errors::MigrateError>`

(expected type parameter, found struct drivers::pg::Postgres) [E0308]

Is there any way to work around that?

The full code is available.


回答1:


In this function:

fn get_driver<T: Driver + Sized>(url: &str) -> MigrateResult<T>

T is a type parameter. It is chosen by the caller of the function.

It looks like you want to a return a different type based on the value of url. But Rust is statically-typed: the type of any expression at any point in the code needs to be known at compile-time. (Even generics get specialized to concrete types when they’re used.) The way to deal with this is to use trait objects:

For example, in:

fn get_driver(url: &str) -> MigrateResult<Box<Driver>>

Box<Driver> is a fat pointer made of a pointer to the value and a pointer to the virtual call table for the a concrete type that implements the Driver trait. That vtable contains pointers to the code for each method of the trait.

Read more at http://doc.rust-lang.org/book/trait-objects.html



来源:https://stackoverflow.com/questions/34708584/how-to-return-an-instance-of-a-trait

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!