Structs and classes are two ways to structure and store your data. We'll start by covering structs, and extend that knowledge with classes.
Structs, like classes, aren't explicitly available in every language, so for now we'll focus on C and Rust.
A basic layout of a struct looks like:
x// Rust example
struct Person {
name: String,
age: i32,
}
(The equivalent in C would look like)
xxxxxxxxxx
// C example
struct Person {
char* name;
int age;
};
The name
and age
properties are called fields. You'll notice that we provide the type for our fields, but never set a value. That's because we declare the layout of a struct here, not actually use it. You can think of structs as a sort of blueprint for data structuring.
To actually use these structs, it would look something like:
x
// Rust example
let Bob: Person = Person {
name: "Bob".to_string(),
age: 22
};
println!("{}", Bob.age);
xxxxxxxxxx
struct Person Bob = { "Bob", 22 };
printf("%d\n", Bob.age);
Classes are an object oriented pattern, notably found in Python, C++, Java, and C#, and JavaScript 2016+. Declaring a class looks something like:
x
# C++ example
using std::string;
class Person {
public:
string name;
int age;
};
(our variables are under public
because that means all functions can access them)
Similar examples include:
x
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
(see explanation of self
later in this article)
In Python, all object specific variables have to go in the constructor. The constructor function of a class is a special function that is called when an instance of the class is created. A similar example in C++ looks like:
x
class Person {
public:
string name;
int age;
Person(string name, int age) {
this->name = name;
this->age = age;
}
};
(In C++, the this
keyword is equivalent to Python's self
, except it's a pointer)
This code will make it so that whenever we create a new instance of our Person
class, it takes a string and an int parameter and sets its properties to the provided arguments.
Methods of a class are functions that you can call on a specific object. Taking our person example earlier, if we added a method called print_age()
, it would look like:
x
# Python example
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def print_age(self):
print(self.age)
Bob = Person("Bob", 22)
Bob.print_age()
You'll see our method takes a parameter self
, and yet we don't pass that when we use it. This is because in Python (and Rust), a method that takes self is automatically considered a method, whereas a function that doesn't take self is considered to be static (more on this later). When you declare self as the first parameter in one of these languages, it's automatically passed.
While Rust doesn't explicitly have the class keyword, you can define methods and functions on structs using impl
:
x
struct Person {
name: String,
age: i32,
}
impl Person {
fn print_age(&self) {
println!("{}", self.age);
}
}
(Note that we take a reference to self in Rust, due to it's unique rules)
Inheritance is the main difference between classes and structs. Inheritance means a sub-class can inherit fields and methods from it's parent class. Let's look at an example in Python first, because it's simpler:
x
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def print_age(self):
print(self.age)
class Worker(Person):
def __init__(self, name, age, salary):
self.name = name
self.age = age
self.salary = salary
Chef = Worker("Robert", 23, 234000)
Chef.print_age()
Here, we defined a class Worker
as a sub-class of Person
, using the brackets. You can see that even though we never created a print_age()
method on the Worker class, it was inherited from the Person
class, and therefore still works.
A similar example in C++ can be seen here:
xxxxxxxxxx
class Person {
public:
string name;
int age;
Person(string name, int age) {
this->name = name;
this->age = age;
}
void print_age() {
cout << this->age << endl;
}
};
class Worker : public Person {
public:
int salary;
Worker(string name, int age, int salary) : Person(name, age) {
this->name = name;
this-> age = age;
this-> salary = salary;
}
};