Is it possible to extend traits?
I want to create a new trait which is extended from multiple base traits. Is this possible ?
Also, is it possible to implement multiple traits at once? Something like
impl A,B for X {
..
}
Is it possible to extend traits?
I want to create a new trait which is extended from multiple base traits. Is this possible ?
Also, is it possible to implement multiple traits at once? Something like
impl A,B for X {
..
}
Rust has trait inheritance, it looks like this:
pub trait A {}
pub trait B: A {}
However, this does not mean that if a type extends B
it will automatically extends A
; trait inheritance is just a way to specify requirements, that is, trait B: A
means that we can know that if some type T
implements B
, it also necessarily implements A
.
Naturally, you can use this to specify that a trait extends a combination of other traits:
pub trait Something: Clone + Send + WhateverOtherTrait {}
Again, it just means that every type which implements Something
must also implement Clone
, Send
and WhateverOtherTrait
.
Implementing multiple traits at the same time is not possible. I think this is because in the vast majority of situations traits are sufficiently different so such implementation won't work anyway.
On the other hand, to specify that if a type extends A
it will also automatically extend B
you can use:
impl<T: A> B for T {}
in case you specified multiple types:
impl<T: Clone + Send + WhateverOtherTrait> Something for T {}
EDITED: previous version confused A: B
with B: A
Because of this:
I found it's more convinenient to think about this feature as "type bounds" on trait implementor, than as a trait inheritance. Once you call it type bounds, it makes things more clear: you just declare you have to implement these traits for T in order to be able to implement the trait.
Imagine situation, when you need to implement two traits with the same method names, e.g. Display
and Debug
: both have method fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
. How can you distringuish different implementations of the method for these traits if you do it at the same time (impl Display + Debug for MyType {}
)?
Isn't it the other way around? That is, if type T implements trait A, trait B is implemented as well.
yea... no idea where my brain was while I was writing it...
If two different traits have methods with the same name, you can use universal function call syntax (UFCS) to distinguish them:
UFCS is about calling methods. I was talking about implementing methods, answering OP's answer.
Oh, I missed that. Sorry!
A simple example based on the above discussion
trait OnOff{
fn set_onoff(&self, b :bool){
println!("OnOff Default");
}
}
trait Brightness{
fn set_brightness(&self, brightness: i32){
println!("Brightness Default");
}
}
//Now any type which implements 'Light' should implement 'OnOff'
//& 'Brightness' as well
trait Light: OnOff + Brightness{ }
struct MyLight{
state: bool
}
//impl <MyLight: OnOff + Brightness>Light for MyLight{}
impl Light for MyLight{}
impl OnOff for MyLight{}
impl Brightness for MyLight{
fn set_brightness(&self, brightness: i32){
println!("Brightness = {}", brightness);
}
}
fn main(){
let my_light = MyLight{state: false};
my_light.set_onoff(true);
my_light.set_brightness(100);
}
Now what is the difference between these two
impl <MyLight: OnOff + Brightness>Light for MyLight{}
(vs)
impl Light for MyLight{}
Both are asking me to implement OnOff
and Brightness
impl<MyLight: OnOff + Brightness> Light for MyLight {}
this one is 100% equal to
impl<T: OnOff + Brightness> Light for T {}
and implements the Light
trait for all types that implement OnOff
and Brightness
. Even for types that someone created in another crate that uses your crate.
The other version
impl Light for MyLight {}
implements Light
only for the MyLight
struct
Good point. Thanks.
Working. Thanks