Let there be a trait PharmaChemical
, representing a pharmaceutical chemical.
pub trait PharmaChemical{
/// Other less interesting routine functions
fn affinity(&self, other : &Self) -> f64;
}
The function affinity
basically allows one to compute a scalar between two structs of the same type implementing PharmaChemical
. I would like this affinity
function to remain.
HydrogenoidChemical
, OxygenoidChemical
, NitrogenoidChemical
etc can be assumed to be structs which implement PharmaChemical
.
My work requires me to implement another trait ChemicalPool
-- representing a collection of chemicals for analysis. An example is below :
pub trait ChemicalPool{
/// Returns the name of the pool.
fn name(&self) -> &str;
/// Should return the chemicals in the pool
fn chemicals(&self) -> &[Box<dyn PharmaChemical>];
}
Now, I get the error which says that dyn PharmaChemical
cannot be made into an object. For a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically
The compiler further says that if I move the affinity
function out the trait the error can be handled. The affinity
function is the problem because it has a Self
parameter.
During run-time, a pool can contain many different types of chemicals. And we compute affinity
for every pair of chemicals. If the two chemicals are not of the same type ( e.g :- HydrogenoidChemical
), it would result in a panic!
. This is infact one of the ways of initial-phase testing to remove unnecessary chemicals from the pool. The chemicals
function is often needed to get a slice of chemicals in the pool.
Now I come from a C++ background and so I ask : Am I modelling the problem wrong that does not conform to the Rust way of thinking ? How can I continue using a function like affinity
while, keeping a dynamic collection of objects which I can return as a slice ?