Why derive is needed (Theory)
[derive(...)] tells Rust to auto-generate implementations of common traits for your type, like:
Debug (so you can print with {:?})
Clone (so you can copy values)
PartialEq (so you can compare with ==)
Default (so you can create default values)
how to print your struct (Debug)
how to compare (PartialEq, Eq, Ord)
how to copy (Clone, sometimes Copy)
how to create default values (Default)
how to use as key in HashMap (Hash)
This saves a lot of boilerplate.
Different kinds of derive in Rust (most used)
Full Rust program (covers all derives)
use std::collections::{HashMap, HashSet};
// 1) Debug, 2) Clone, 3) PartialEq/Eq, 5) Hash, 6) Default
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
struct User {
name: String,
age: u32,
}
// 4) PartialOrd/Ord for sorting
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
struct Score(i32);
// 2) Copy example (cheap copy type)
#[derive(Debug, Copy, Clone, PartialEq)]
struct Point {
x: i32,
y: i32,
}
fn main() {
println!("--- Debug + Default ---");
let u_default = User::default();
println!("default user = {:?}", u_default);
println!("\n--- Clone ---");
let u1 = User { name: "Ashwani".to_string(), age: 30 };
let u2 = u1.clone();
println!("u1 = {:?}", u1);
println!("u2 = {:?}", u2);
println!("\n--- PartialEq + Eq ---");
println!("u1 == u2 ? {}", u1 == u2);
println!("\n--- Hash (HashSet / HashMap keys) ---");
let mut set = HashSet::new();
set.insert(u1.clone());
set.insert(u2.clone()); // duplicate, will not add again
println!("HashSet size (should be 1) = {}", set.len());
let mut map: HashMap<User, String> = HashMap::new();
map.insert(u1.clone(), "Premium".to_string());
println!("User tier = {}", map.get(&u1).unwrap());
println!("\n--- PartialOrd + Ord (Sorting) ---");
let mut scores = vec![Score(90), Score(50), Score(75), Score(75)];
scores.sort(); // ascending
println!("sorted scores = {:?}", scores);
println!("\n--- Copy (no .clone needed) ---");
let p1 = Point { x: 10, y: 20 };
let p2 = p1; // copy happens
println!("p1 = {:?}, p2 = {:?}", p1, p2);
// show that p1 still usable (because Copy)
let p3 = p1;
println!("p3 = {:?}", p3);
}
Output (Rust)
--- Debug + Default ---
default user = User { name: "", age: 0 }
--- Clone ---
u1 = User { name: "Ashwani", age: 30 }
u2 = User { name: "Ashwani", age: 30 }
--- PartialEq + Eq ---
u1 == u2 ? true
--- Hash (HashSet / HashMap keys) ---
HashSet size (should be 1) = 1
User tier = Premium
--- PartialOrd + Ord (Sorting) ---
sorted scores = [Score(50), Score(75), Score(75), Score(90)]
--- Copy (no .clone needed) ---
p1 = Point { x: 10, y: 20 }, p2 = Point { x: 10, y: 20 }
p3 = Point { x: 10, y: 20 }
Java comparison (what equals “derive”?)
Java has no built-in derive like Rust.
You must manually implement:
toString() (Debug)
equals() / hashCode() (PartialEq/Eq/Hash)
copying (Clone or copy constructor)
sorting (Comparable)
default values (constructors)
Java records reduce boilerplate but still not as flexible as Rust derive.
Full Java program (similar behavior)
import java.util.*;
public class Main {
static class User {
String name;
int age;
User() { this.name = ""; this.age = 0; } // Default
User(String name, int age) { this.name = name; this.age = age; }
// Debug equivalent
public String toString() { return "User{name='" + name + "', age=" + age + "}"; }
// PartialEq + Eq + Hash equivalents
@Override public boolean equals(Object o) {
if (!(o instanceof User)) return false;
User other = (User) o;
return Objects.equals(this.name, other.name) && this.age == other.age;
}
@Override public int hashCode() { return Objects.hash(name, age); }
// Clone/copy (recommended: copy constructor)
User(User other) { this.name = other.name; this.age = other.age; }
}
static class Score implements Comparable<Score> {
int value;
Score(int value) { this.value = value; }
@Override public int compareTo(Score o) {
return Integer.compare(this.value, o.value);
}
public String toString() { return "Score(" + value + ")"; }
}
static class Point {
int x, y;
Point(int x, int y) { this.x = x; this.y = y; }
public String toString() { return "Point{x=" + x + ", y=" + y + "}"; }
}
public static void main(String[] args) {
System.out.println("--- toString + default constructor ---");
User uDefault = new User();
System.out.println("default user = " + uDefault);
System.out.println("\n--- Copy (clone-like) ---");
User u1 = new User("Ashwani", 30);
User u2 = new User(u1);
System.out.println("u1 = " + u1);
System.out.println("u2 = " + u2);
System.out.println("\n--- equals ---");
System.out.println("u1 equals u2 ? " + u1.equals(u2));
System.out.println("\n--- HashSet / HashMap keys ---");
Set<User> set = new HashSet<>();
set.add(new User(u1));
set.add(new User(u2)); // duplicate
System.out.println("HashSet size (should be 1) = " + set.size());
Map<User, String> map = new HashMap<>();
map.put(u1, "Premium");
System.out.println("User tier = " + map.get(u1));
System.out.println("\n--- Sorting (Comparable) ---");
List<Score> scores = Arrays.asList(new Score(90), new Score(50), new Score(75), new Score(75));
Collections.sort(scores);
System.out.println("sorted scores = " + scores);
System.out.println("\n--- Reference copy (no Copy trait in Java) ---");
Point p1 = new Point(10, 20);
Point p2 = p1; // reference copy (not deep copy)
System.out.println("p1 = " + p1 + ", p2 = " + p2);
}
}
Output (Java)
--- toString + default constructor ---
default user = User{name='', age=0}
--- Copy (clone-like) ---
u1 = User{name='Ashwani', age=30}
u2 = User{name='Ashwani', age=30}
--- equals ---
u1 equals u2 ? true
--- HashSet / HashMap keys ---
HashSet size (should be 1) = 1
User tier = Premium
--- Sorting (Comparable) ---
sorted scores = [Score(50), Score(75), Score(75), Score(90)]
--- Reference copy (no Copy trait in Java) ---
p1 = Point{x=10, y=20}, p2 = Point{x=10, y=20}
Key differences (Rust vs Java)
Top comments (0)