Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way other than traits to add methods to a type I don't own?

Tags:

rust

I'm trying to extend the Grid struct from the piston-2dgraphics library. There's no method for getting the location on the window of a particular cell, so I implemented a trait to calculate that for me. Then, I wanted a method to calculate the neighbours of a particular cell on the grid, so I implemented another trait.

Something about this is ugly and feels unnecessary seeing as how I'll likely never use these traits for anything other than this specific grid structure. Is there another way in Rust to extend a type without having to implement traits each time?

like image 884
tsujin Avatar asked Oct 27 '15 19:10

tsujin


People also ask

When should I use traits Rust?

We can use traits as function parameters to allow the function to accept any type that can do x , where x is some behavior defined by a trait. We can also use trait bounds to refine and restrict generics, such as by saying we accept any type T that implements a specified trait.

Can traits have properties Rust?

Nothing in Rust prevents a trait from having a method with the same name as another trait's method, nor does Rust prevent you from implementing both traits on one type. It's also possible to implement a method directly on the type with the same name as methods from traits.

Can traits have fields?

Traits can't have fields. If you want to provide access to a field from a trait, you need to define a method in that trait (like, say, get_blah ).

How do traits work Rust?

A trait defines functionality a particular type has and can share with other types. We can use traits to define shared behavior in an abstract way. We can use trait bounds to specify that a generic type can be any type that has certain behavior.


1 Answers

As of Rust 1.27, no, there is no other way. It's not possible to define inherent methods on a type defined in another crate.

You can define your own trait with the methods you need, then implement that trait for an external type. This pattern is known as extension traits. The name of extension traits, by convention, ends with Ext, to indicate that this trait is not meant to be used as a generic bound or as a trait object. There are a few examples in the standard library.

trait DoubleExt {     fn double(&self) -> Self; }  impl DoubleExt for i32 {     fn double(&self) -> Self {         *self * 2     } }  fn main() {     let a = 42;     println!("{}", 42.double()); } 

Other libraries can also export extension traits (example: byteorder). However, as for any other trait, you need to bring the trait's methods in scope with use SomethingExt;.

like image 144
Francis Gagné Avatar answered Sep 28 '22 13:09

Francis Gagné