Generics vs type erasure

So just in case this is news, apologies if you're already familiar: heterogeneous collections (across all typed languages really) use basically one of two methods to get a common type most of the time: abstract the external interface behind a trait and hide the concrete type behind dyn, eg. Box<dyn Resolution>; or wrapping each of the valid types in an enum.

The former is called "open polymorphism" because it means you can add more concrete types without changing any of the using code so long as you can implement the trait, and the latter "closed polymorphism" because the using code knows exactly which types are in use.

Downcasting is a bit of a middle ground, but you can think of it as the first but with the interface "are you this type?". It's generally a bad idea.

You might be asking for open polymorphism, but with the ability to share most of the data between the different types, which might look something like:

struct ResolutionImpl<T> { ... } 

trait Resolution { ... } 

impl<T: ResolutionModel> Resolution for ResolutionImpl<T> { ... } 

but I really wonder why, it seems much simpler to provide ResolutionModel as an enum.

Thanks for additional explanation. I am far from being an expert but I understand the difference between the two. Open polymorphism feels more appropriate to me because of two reasons:

  • Catalogue of possible ResolutionModels is open. I will be adding more standard ones, e.g. years, months, weeks, quarters etc. All these exist in my field of work (energy markets). I feel that it is easier to maintain big and open catalogue with trait objects rather than enums.

  • Potentially I might be adding non-standard ResolutionModels which cannot be generated by a function and will have a form of (potentially long) vector of chrono::NaiveDateTime. Due to different memory representation trait objects again seem more appropriate.

Does it make sense?

Ok, does the suggested code outline make sense for that then?

Yes with the exception that (as determined above) Resolution cannot be generic on ResolutionModel since concrete type of ResolutionModel is not known prior to SQL query. So I have to use polymorphism and will probably use trait objects for this purpose. Many thanks for help.

I think you've missed the relevant detail with that outline: now it's the internal ResolutionImpl that's generic on ResolutionModel, and the public interface is the type erased trait Resolution, so you're returning a Box<dyn Resolution>, which contains, for example, a ResolutionImpl<Hours>.

This, to some extent, gives you the best of both worlds: a generic implementation and an open polymorphic interface.

Thanks. Right, I did missed it. I will look into this and get back.

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.