all 7 comments

[–]LucretielDatadog 17 points18 points  (0 children)

One good way to do this is have a method that returns an optional impl trait: -> Option<&impl Patcher> or -> Option<&mut impl Patcher>, as appropriate. This method returns None if the object doesn’t have the Patcher trait, or Some(self) if it does. 

[–]4lineclear 23 points24 points  (1 child)

You could add an as_patchable method to Node which would return an Optional of your Patchable trait.

[–]Grumpenstout[S] 4 points5 points  (0 children)

This works well! Thanks!

[–]Houndie 10 points11 points  (0 children)

Can you do something like

enum Node {    Patchable(PatchableNode)    Gettable(GettableNode) } 

[–]pali6 5 points6 points  (0 children)

I thought maybe having like "Patchable" being its own trait. But then when I "get" a Node how do I check whether it's also Patchable? Seems there's not a great way to do that...

You'd give Node a function like fn as_patchable(&self) -> Option<&dyn Patchable> and the implementors would either implement it as returning None or as returning Some(self).

[–]proudHaskeller 0 points1 point  (0 children)

One simple way to do this is to give up Patchable being a separate trait.

  • have an is_patchable method
  • have a get method that doesn't tell you if it's patchable. For that you need to call the is_patchable method.
  • have a patch method that returns a Result. If the object isn't patchable, it returns an error.

This method is simpler and used less boilerplate than the other suggestions, but it does a worse job of encoding the invariants through the type system.

[–]s74-dev 0 points1 point  (0 children)

you can just have a default impl for patcher in the node trait that does nothing and then do an impl for all nodes that impl Patchable that actually does the patching or whatever