Introduction

Hello there, welcome to the very first lesson of this course on Fundamental Rust Concepts for Design Patterns! In this starting lesson, we will dive into the concept of structs in Rust. Structs, or structures, play a vital role in Rust's ability to organize data efficiently, allowing you to create custom data types that enhance code readability and maintain a clean architecture. Structs help form the building blocks for complex systems in Rust, and understanding them will pave the way for mastering more advanced design patterns later in the course.

Defining Structs

Let's start by defining a struct in Rust. A struct is essentially a way to group related data together. Think of it as creating a new data type that can have multiple pieces of data, called fields, associated with it.

Here's how you can define a simple struct to represent a Point in a 2D space:

In this example:

  • struct Point defines a new struct named Point.
  • Inside the curly braces {}, we define the fields x and y, both of which are of type i32, representing integer coordinates of the point in a 2-dimensional plane.

Rust also supports tuple structs, which are struct variants without named fields, and unit structs, which have no fields at all and are useful when implementing traits:

Creating and Using Struct Instances

To create an instance of our Point struct:

You can access struct fields using dot notation:

Rust also provides a convenient struct update syntax to create a new instance based on an existing one:

Implementing Methods for Structs

To extend the functionality of structs, Rust allows you to implement both methods and associated functions. Both are defined within impl blocks, but they serve different purposes:

  1. Methods are functions that operate on an instance of the struct and take self as their first parameter, which is used to access the struct's data.
  2. Associated functions are functions that don't take self as a parameter: they're associated with the type itself rather than any particular instance. For example, constructors are usually implemented as associated functions.

Let's see both in action with our Point struct:

In this implementation:

  • new is an associated function called using Point::new(x, y) that creates and returns an instance of Point. It doesn't need an instance to work with, which is why it doesn't take self. Please note that using new as a constructor is a common convention in Rust, but you can actually use any name for associated functions that create instances.
  • distance_from_origin is a method that takes &self (a reference to the instance). It can access the instance's data through self.x and self.y.
  • Self is an alias for the type in the impl block (in this case, Point).

Methods can take self in three different ways:

  • self: Takes ownership of the instance, giving the method full control but consuming the instance
  • &self: Immutably borrows the instance, allowing the method to read but not modify the data
  • &mut self: Mutably borrows the instance, allowing the method to both read and modify the data

In our example, distance_from_origin only needs to read the values, so it borrows self immutably with &self If these terms about ownership and borrowing seem a bit confusing right now, don't worry! We'll be covering these core Rust concepts in an upcoming lesson.

Applying Structs in a Rust Program

Here's how you can use the Point struct and the methods we've implemented in a Rust program:

In this program:

  • We create a Point instance using the new method.
  • We calculate the distance from the origin using distance_from_origin.
  • The println! macro is then used to display the result.

This demonstrates how using structs and methods effectively can help structure and simplify your program logic.

Summary and Preparation for Practice

In this lesson, we explored how to define and use structs in Rust, including creating instances and implementing methods. We covered regular structs, tuple structs, and unit structs, along with field access and update syntax. We used a Point struct to illustrate these concepts, showing how to encapsulate data and functionality within a structured format. This foundational understanding prepares you to tackle more complex data structures and design patterns in future lessons.

As you move on to the practice exercises, focus on applying these concepts by creating and manipulating your own structs. These exercises will reinforce your understanding and help you become more comfortable using structs in your Rust programs. Good luck, and enjoy the journey of mastering Rust design patterns!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal