Arrays are used to represent a homogeneous collection of values. Similarly, a structure is another user defined data type available in Rust that allows us to combine data items of different types, including another structure. A structure defines data as a key-value pair.
The struct keyword is used to declare a structure. Since structures are statically typed, every field in the structure must be associated with a data type. The naming rules and conventions for a structure is like that of a variable. The structure block must end with a semicolon.
struct Name_of_structure { field1:data_type, field2:data_type, field3:data_type }
After declaring a struct, each field should be assigned a value. This is known as initialization.
let instance_name = Name_of_structure { field1:value1, field2:value2, field3:value3 }; //NOTE the semicolon Syntax: Accessing values in a structure Use the dot notation to access value of a specific field. instance_name.field1 Illustration struct Employee { name:String, company:String, age:u32 } fn main() { let emp1 = Employee { company:String::from("Howcodex"), name:String::from("Mohtashim"), age:50 }; println!("Name is :{} company is {} age is {}",emp1.name,emp1.company,emp1.age); }
The above example declares a struct Employee with three fields – name, company and age of types. The main() initializes the structure. It uses the println! macro to print values of the fields defined in the structure.
Name is :Mohtashim company is Howcodex age is 50
To modify an instance, the instance variable should be marked mutable. The below example declares and initializes a structure named Employee and later modifies value of the age field to 40 from 50.
let mut emp1 = Employee { company:String::from("Howcodex"), name:String::from("Mohtashim"), age:50 }; emp1.age = 40; println!("Name is :{} company is {} age is {}",emp1.name,emp1.company,emp1.age);
Name is :Mohtashim company is Howcodex age is 40
The following example shows how to pass instance of struct as a parameter. The display method takes an Employee instance as parameter and prints the details.
fn display( emp:Employee) { println!("Name is :{} company is {} age is {}",emp.name,emp.company,emp.age); }
Here is the complete program −
//declare a structure struct Employee { name:String, company:String, age:u32 } fn main() { //initialize a structure let emp1 = Employee { company:String::from("Howcodex"), name:String::from("Mohtashim"), age:50 }; let emp2 = Employee{ company:String::from("Howcodex"), name:String::from("Kannan"), age:32 }; //pass emp1 and emp2 to display() display(emp1); display(emp2); } // fetch values of specific structure fields using the // operator and print it to the console fn display( emp:Employee){ println!("Name is :{} company is {} age is {}",emp.name,emp.company,emp.age); }
Name is :Mohtashim company is Howcodex age is 50 Name is :Kannan company is Howcodex age is 32
Let us consider a function who_is_elder(), which compares two employees age and returns the elder one.
fn who_is_elder (emp1:Employee,emp2:Employee)->Employee { if emp1.age>emp2.age { return emp1; } else { return emp2; } }
Here is the complete program −
fn main() { //initialize structure let emp1 = Employee{ company:String::from("Howcodex"), name:String::from("Mohtashim"), age:50 }; let emp2 = Employee { company:String::from("Howcodex"), name:String::from("Kannan"), age:32 }; let elder = who_is_elder(emp1,emp2); println!("elder is:"); //prints details of the elder employee display(elder); } //accepts instances of employee structure and compares their age fn who_is_elder (emp1:Employee,emp2:Employee)->Employee { if emp1.age>emp2.age { return emp1; } else { return emp2; } } //display name, comapny and age of the employee fn display( emp:Employee) { println!("Name is :{} company is {} age is {}",emp.name,emp.company,emp.age); } //declare a structure struct Employee { name:String, company:String, age:u32 }
elder is: Name is :Mohtashim company is Howcodex age is 50
Methods are like functions. They are a logical group of programming instructions. Methods are declared with the fn keyword. The scope of a method is within the structure block.
Methods are declared outside the structure block. The impl keyword is used to define a method within the context of a structure. The first parameter of a method will be always self, which represents the calling instance of the structure. Methods operate on the data members of a structure.
To invoke a method, we need to first instantiate the structure. The method can be called using the structure's instance.
struct My_struct {} impl My_struct { //set the method's context fn method_name() { //define a method } }
The following example defines a structure Rectangle with fields − width and height. A method area is defined within the structure's context. The area method accesses the structure's fields via the self keyword and calculates the area of a rectangle.
//define dimensions of a rectangle struct Rectangle { width:u32, height:u32 } //logic to calculate area of a rectangle impl Rectangle { fn area(&self)->u32 { //use the . operator to fetch the value of a field via the self keyword self.width * self.height } } fn main() { // instanatiate the structure let small = Rectangle { width:10, height:20 }; //print the rectangle's area println!("width is {} height is {} area of Rectangle is {}",small.width,small.height,small.area()); }
width is 10 height is 20 area of Rectangle is 200
Static methods can be used as utility methods. These methods exist even before the structure is instantiated. Static methods are invoked using the structure's name and can be accessed without an instance. Unlike normal methods, a static method will not take the &self parameter.
A static method like functions and other methods can optionally contain parameters.
impl Structure_Name { //static method that creates objects of the Point structure fn method_name(param1: datatype, param2: datatype) -> return_type { // logic goes here } }
The structure_name :: syntax is used to access a static method.
structure_name::method_name(v1,v2)
The following example uses the getInstance method as a factory class that creates and returns instances of the structure Point.
//declare a structure struct Point { x: i32, y: i32, } impl Point { //static method that creates objects of the Point structure fn getInstance(x: i32, y: i32) -> Point { Point { x: x, y: y } } //display values of the structure's field fn display(&self){ println!("x ={} y={}",self.x,self.y ); } } fn main(){ // Invoke the static method let p1 = Point::getInstance(10,20); p1.display(); }
x =10 y=20