Struct types

Structs in Rust have a few different ways to be defined, each having their own use cases.

Structs with named fields

The most common one is structs with named fields, we have already discussed this in the previous lesson.

Here's an example of a struct with named fields:

struct Point {
    name: String,
    x: i32,
    y: i32,
}

Each field in the struct can have a different type. The fields can be accessed using the dot notation:

let p = Point { name: String::from("origin"), x: 0, y: 0 };
println!("The point is at ({}, {})", p.x, p.y);

Tuple structs

Tuple structs do not have named fields, but rather just the types of the fields. They are especially useful when you know the struct type doesn't need too many fields, so there's no need to name them.

Here's an example of a tuple struct:

struct Color(i32, i32, i32);

In the example above of a Color struct, we don't need to name the fields, as it's clear that the three integers represent the red, green, and blue values of the color.

Tuple structs are accessed using the dot notation and the index of the field, the first field has index 0, the second has index 1, and so on:

let c = Color(255, 0, 0);
println!("The color is RGB ({}, {}, {})", c.0, c.1, c.2);

Unit structs

Unit structs are structs that don't have any fields. They are useful when you need to implement a trait on a type, but don't need to store any data. They are called unit structs because they have the type of () (unit type), as discussed earlier in the data types lesson.

If you only need to implement a trait on a type, you can use a unit struct:

struct Empty;

Unit structs are useful when you need to implement a trait on a type, but don't need to store any data.

Here's an example of a unit struct. Let's say we have a trait Describable that defines a method describe. Traits are used in Rust to define shared behavior that types can implement (we'll cover them in detail later). Here's how you can define and implement this:

// Define a unit struct
struct UnitStruct;
 
// Define a trait with a method `describe`
trait Describable {
    fn describe(&self) -> String;
}
 
// Implement the Describable trait for UnitStruct
impl Describable for UnitStruct {
    fn describe(&self) -> String {
        "This is a unit struct implementing the Describable trait.".to_string()
    }
}
 
fn main() {
    let another_unit = UnitStruct;
    println!("{}", another_unit.describe()); // Call the describe method and print the result
}

As you can see, we've changed the syntax just a little bit when implementing a trait to a struct. Instead of impl StructName, we use impl TraitName for StructName.

But the implementation is exactly the same as soon as the method signature is the same, in this case it is a method describe that returns a String.

Conclusion

There are three ways to define structs in Rust: structs with named fields, tuple structs, and unit structs. Each has its own use cases, and you should choose the one that best fits your needs. Structs with named fields are the most common and are used when you need to name each field. Tuple structs are used when you don't need to name the fields, and unit structs are used when you don't need to store any data.


In the next lesson, we're going to understand how structs work in terms of ownership and how they're stored in memory.

Rustfinity.com

Links

  1. Home
  2. Learn Rust
  3. Get Started
  4. Practice Rust
  5. Challenges
  6. Open source

Socials

  1. GitHub
  2. X

Legal

  1. Privacy Policy
  2. Terms of Service