trait in rust, and comparison with interface in java
Hi, everyone, this is my fourth blog post for rust, in this blog post, I will talk about something about trait in rust. This blog might be more likely to a summary of my views of traits and interface.
The first time I come into rust and get to know that there is a concept named trait which is much similar to interface in other languages such as java. Then I just think ”haha, that should be easy to learn”.
Interface I usually use in java:
Basic use:
interface Animal { public void eat(); public void travel(); } public class MammalInt implements Animal{ public void eat(){ System.out.println("Mammal eats"); } public void travel(){ System.out.println("Mammal travels"); } public int noOfLegs(){ return 0; } public static void main(String args[]){ MammalInt m = new MammalInt(); m.eat(); m.travel(); } }
other use in spring framework to isolate the implementation and the raw interface.
public interface CommentService { void addNewComment(Comment comment); void deleteCommentByid(int commentId); void praiseCommentById(Integer commentId); List<Comment> getAllComment(); }
So, the first time I see implementing a trait for struct in rust: Ok, I get it, quite similar to java.
Then, the first time I see implementing a trait for enum in rust: I said: ”???”
Code here.
pub enum Die { D4, D6, D8, D10, D12, D20, } trait Rollable { fn roll(&self) -> u8; } impl Rollable for Coin { fn roll(&self) -> u8 { get_random_value(2) } } impl Rollable for Die { fn roll(&self) -> u8 { match *self { Die::D4 => get_random_value(4), Die::D6 => get_random_value(6), Die::D8 => get_random_value(8), Die::D10 => get_random_value(10), Die::D12 => get_random_value(12), Die::D20 => get_random_value(20), } }
Actually, I was so confused: Wow, why can I do it? This is a enum! But why it can be implemented with traits?
To clearly solve this question, we need to clarify:
Firstly, we can implement the struct with our methods using impl , right? Trait just provide a reusable method set with no implementation, this is much more similar to the interface in java and easy to understand.
Then, let’s check out the enum in rust. Enum in rust is much more powerful than that in java. It can carry some data! I think this is the primary reason that why we are allowed to implement trait into the enum. Even If the enum in rust is just simple enough and do not have followed data, do not forget we usually use match to resolve the enum, then, we can place some code in the match block of each case. If these code in the match block can be similar, things could be simplified: we can use trait to replace them! Then, we just need to implement trait for the enum and use the method in trait for every case (or item) in the enum!
If there are some data followed up in the item of enum, then this can be much more better: just put your data into the implemented trait method, then everything finished.
I just feel that rust is trying to make enum as powerful as it can, every item in the enum is just like separated struct (might be inaccurate but still feel like this), then they can make full use of trait. Therefore, the use of trait has been wider and help to form a much more special format for “interface” in rust. This is quite cool!
Then, let’s come to the basic data type, we will talk about i32 here.
• I32 has implemented these traits: Copy • Clone • Add, Sub, Mul, Div, Rem • AddAssign, SubAssign, MulAssign, DivAssign, RemAssign • PartialEq, Eq • PartialOrd, Ord • Debug • Hash • Sum,Product • From<T>,Into<T> • Default
You can see, a large part of method for i32 are implemented with trait, this just reversed what I thought I knew. That is because I use java most of the time before, and, for Integer in java, some of its method are concluded by the class itself, and a small portion of the methods are implemented with interfaces. “Rust's design philosophy encourages the use of traits to define shared behavior.” This is what I get from one blog. Now I have to say, it’s really amazing.
Even in the println!, like println!("{}",value);
the value needs to implement certain traits, then it can be formated and printed out.
That is to say,
For a type's value to be processed by the println! macro, the type must implement at least one of the std::fmd::Display or std::fmt::Debug traits.
Additionally, there are other specialized formatting traits, such as std::fmt::Octal, std::fmt::Pointer, std::fmt::Binary, etc., that allow using specific formatting options within the println! macro.
pretty amazing design!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [翻译] 为什么 Tracebit 用 C# 开发
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· 2分钟学会 DeepSeek API,竟然比官方更好用!
· .NET 使用 DeepSeek R1 开发智能 AI 客户端
· 刚刚!百度搜索“换脑”引爆AI圈,正式接入DeepSeek R1满血版