Object-oriented programming. Introduction

codecrafters
8 min readJul 21, 2015

--

OOP concept

Object-oriented programming is an approach for developing programming code, which allows considering designed system as a set of interacting objects.

Such approach reflects our normal perception of objects and phenomenon which surrounds us. We get used to talk about such objects and phenomenon like something certain and independent. Our perception interprets the world as a set of diverse objects which possess with certain features and functions.

Entity

Entity — is some logical one, complete and independent unit of information. This is independently existing and unambiguously defined element of subject domain.

Entity can be represented in the form of both real, physically existing object (table, chair, car, pen, or donkey) and abstract (point in space, vector, news category, forum post, or user). Entity can be represented through either a whole city or separate house in this city, or maybe a single brick of this house. Everything depends on the required detalization level of the system.

For instance, if we want to talk about cargo shipping between two cities then we are completely out of interest about mass of a certain brick, its color and durability. We are interest in some general city characteristics: number of residents, economical features, geographical location and etc. But if our system should perform calculations for building demolition then characteristics of each brick would be very much even interested.

It turns out that entity is really abstract definition. And dependently on situation entity can be represented through molecule or galaxy, Cartesian plane or mathematical function.

Class

It’s a common knowledge that class is something mysterious, complex, inconceivable and requires long and hard study, because this secret knowledge is inherited only from programmer to programmer and exclusively through sex. This is not completely right, although it is possible that some educational facilities teach this sacrament exactly in such way.

According to Wikipedia:

Idea of classes came from works related to data bases associated with investigations in artificial intelligence. Widely applied classifications by humans in zoology, botany, chemistry, machine components highlight main idea that anything can be always represented as a partial case of something more common. Generally, specific apple is some apple and any some apple is a fruit. That is why numerous examples of classes are given through apples and pears in object-oriented programming teaching materials.

Bream and pike are different kinds of fish. But, generally, bream and pike are fish. Shepherd Dog and Poodle are dogs, though different. “Samsung” TV and “Electron” TV are TV (except the second one, because this statement is really controversial).

In other words, class — is some “pattern”, which describes common featured. Class defines “variety”.

Anything can be represented via class. As a matter of fact, class — is a representation of a certain entity in the form of programming code.

How cars are manufactured? Roughly speaking, certain automobile project exists, where all characteristics and its functions are specified. This large book describes everything: mass, maximal speed, tank volume, ability to control, accelerate and slow down motion and many others. Using this projects makes possible to build real cars (create objects), which will possess with all listed characteristics and functions.

In programming sense, class is user data type, based on in-build data types and/or other classes. Class allows describe current entity with inherent characteristics and functions just once.

It is generally accepted for naming classes to use UpperCamelCase. Wherein class name can be short and consist of only one word.

class Car {
};

Or two words:

class SniperRifle {
};

Or even more than two words:

class VeryImportantAbstractEntityItemWithVeryLongName {
};

Object

Once having created a class it is possible to make plenty of objects (instances) of this class. Wherein, each created object will match the type, defined by class, and posses with all listed characteristics and functions.

Once having created a class it is possible to make plenty of objects (instances) of this class. Wherein, each created object will match the type, defined by class, and posses with all listed characteristics and functions.

Class — is user defined data type that is why when creating class objects it is recommended to specify class name as a variable type.

#include <iostream>
class Car {
}
int main() {
Car volvo, mazda, toyota;
Car cars[] = { volvo, mazda, toyota };
for ( int i = 0; i < 3; i++ ) {
std::cout << &cars[i] << std::endl;
}
return 0;}

Attribute

As a rule, entities have some characteristics. Each instance of entity possesses with the same set of characteristics. Meanings of these characteristics can be different from instance to instance.

Car characteristics can be represented, for example, through maximal speed, current speed, number of seats, trunk capacity and other. Dog can have nickname, age, mass and something else.

Attributes describe objects characteristics. Object state is usually described by meanings of its attributes. Having changed attribute meaning we change objects state.

Attributes describe objects characteristics. Object state is usually described by meanings of its attributes. Having changed attribute meaning we change objects state.

Within the context of OOP, attribute is a regular variable, which is being described in a class body and created for each object. We can work with objects attributes selfsame with regular variables, but since attributes are associated with certain object, we can change and work with them with specification of this object.

#include <iostream>
class Car {
public:
int maxSpeed;
int currentSpeed;
};
int main() {
Car car1, car2;
car1.maxSpeed = 260;
car2.maxSpeed = 180;
car1.currentSpeed = 56;
car2.currentSpeed = 82;
std::cout << "maxSpeed:" << std::endl;
std::cout << " car1: " << car1.maxSpeed << std::endl;
std::cout << " car2: " << car2.maxSpeed << std::endl;
std::cout << "currentSpeed:" << std::endl;
std::cout << " car1: " << car1.currentSpeed << std::endl;
std::cout << " car2: " << car2.currentSpeed << std::endl;
car1.currentSpeed += 43; std::cout << "currentSpeed:" << std::endl;
std::cout << " car1: " << car1.currentSpeed << std::endl;
std::cout << " car2: " << car2.currentSpeed << std::endl;

Remember struct? Seems like being completely the same, doesn’t it?

In class description we specified int maxSpeed only once, but used for two times. It becomes possible due to variable maxSpeed is being created separately for each object of class Car. These variables are different. And they are also associated with different objects. This is why addressing them requires specifying object name.

In class description we specified int maxSpeed only once, but used for two times. It becomes possible due to variable maxSpeed is being created separately for each object of class Car. These variables are different. And they are also associated with different objects. This is why addressing them requires specifying object name.

Method

Entities, besides, attributes, as a rule, possess with some functions. Some sort of behaviour exists. A dog can eat food of certain type and with certain speed; car can accelerate and slow down. Wherein performing of those or any others actions somehow impacts on internal condition: eating food makes dog increase its vitality, car motion reduces volume of gas and changes its position in space.

Behaviour in classes is usually described via methods — regular functions, which can receive arguments and return values. These functions are commonly being declared inside of a class and, as well as attributes, they connect with each created object, so that calling these function requires specifying of certain object. You cannot just press the gas pedal without automobile or you cannot just feed some definition of “dog” — you need concrete, existing dog.

Object with called method is accessible inside of this method through special pointer — “this”. By means of this it is possible to address to own attributes and call own methods.

Object with called method is accessible inside of this method through special pointer — “this”. By means of this it is possible to address to own attributes and call own methods.

#include <iostream>
class Car {
public:
int maxSpeed;
int currentSpeed;
void accelerate() {
this->accelerate(8); // calling own method
}
void accelerate(int delta){
this->currentSpeed += delta; // changing own attributes
if ( this->currentSpeed > this->maxSpeed ) {
this->currentSpeed = this->maxSpeed;
}
}
void deccelerate() {
this->deccelerate(12); // calling own method
}
void deccelerate(int delta) {
this->currentSpeed -= delta; // changing own attributes
if ( this->currentSpeed < 0 ) {
this->currentSpeed = 0;
}
}
};
int main() {
Car car1, car2;
car1.maxSpeed = 260;
car2.maxSpeed = 180;
car1.currentSpeed = 50
car2.currentSpeed = 50;
std::cout << "maxSpeed:" << std::endl;
std::cout << " car1: " << car1.maxSpeed << " mph" << std::endl;
std::cout << " car2: " << car2.maxSpeed << " mph" << std::endl;
std::cout << "currentSpeed:" << std::endl;
std::cout << " car1: " << car1.currentSpeed << " mph" << std::endl;
std::cout << " car2: " << car2.currentSpeed << " mph" << std::endl;
car1.accelerate();
car2.deccelerate();
car2.deccelerate(20);
std::cout << std::endl << "currentSpeed:" << std::endl;
std::cout << " car1: " << car1.currentSpeed << " mph" << std::endl;
std::cout << " car2: " << car2.currentSpeed << " mph" << std::endl;
return 0;
}

As you have already understood, class itself is very similar to regular struct. Let us take a look at “evolution” from regular struct to class.

As you have already understood, class itself is very similar to regular struct. Let us take a look at “evolution” from regular struct to class.

Level 1 — struct with external functions:

#include <iostream>
struct Car {
double fuelCapacity;
double fuelAmount;
double fuelConsumption;
};
void drive(Car& car, double distance) {
double fuelNeeded = car.fuelConsumption * distance;
if ( fuelNeeded > car.fuelAmount ) {
std::cout << "Not enough fuel." << std::endl;
return;
}
car.fuelAmount -= fuelNeeded;
std::cout << "Car traveled " << distance << " miles." << std::endl;
}
void refill(Car& car, double fuel) {
double maxRefillVolume = car.fuelCapacity - car.fuelAmount;
if ( fuel > maxRefillVolume ) {
std::cout << "Max fuel amount exceeded!"<< std::endl;
return;
}
car.fuelAmount += fuel;
std::cout << "Car was successfully refilled!" << std::endl;
}
void printStatus(Car& car) {
std::cout << "-- fuel capacity: " << car.fuelCapacity << std::endl;
std::cout << "-- fuel amount: " << car.fuelAmount << std::endl;
std::cout << "-- fuel consumption: " << car.fuelConsumption << std::endl;
}
int main() {
Car toyota = {50.0, 50.0, 0.8};
printStatus(toyota);
drive(toyota, 40.0);
drive(toyota, 30.0);
refill(toyota, 100.0);
printStatus(toyota);
refill(toyota, 30.0);
printStatus(toyota);
return 0;
}

Level 2 — struct with nested functions:

#include <iostream>
struct Car {
double fuelCapacity;
double fuelAmount;
double fuelConsumption;
void drive(double distance) {
double fuelNeeded = fuelConsumption * distance;
if ( fuelNeeded > fuelAmount ) {
std::cout << "Not enough fuel." << std::endl;
return;
}
fuelAmount -= fuelNeeded;
std::cout << "Car traveled " << distance << " miles." << std::endl;
}
void refill(double fuel) {
double maxRefillVolume = fuelCapacity - fuelAmount;
if ( fuel > maxRefillVolume ) {
std::cout << "Max fuel amount exceeded!"<< std::endl;
return;
}
fuelAmount += fuel;
std::cout << "Car was successfully refilled!" << std::endl;
}
void report() {
std::cout << "-- fuel capacity: " << fuelCapacity << std::endl;
std::cout << "-- fuel amount: " << fuelAmount << std::endl;
std::cout << "-- fuel consumption: " << fuelConsumption << std::endl;
}
};
int main() {
Car toyota = {50.0, 50.0, 0.8};
toyota.report();
toyota.drive(40.0);
toyota.drive(30.0);
toyota.refill(100.0);
toyota.report();
toyota.refill(30.0);
toyota.report();
return 0;
}

Level 3 — class:

#include <iostream>
class Car {
public:
double fuelCapacity;
double fuelAmount;
double fuelConsumption;
Car(double capacity, double amount, double consumption) {
fuelCapacity = capacity;
fuelAmount = amount;
fuelConsumption = consumption;
}
void drive(double distance) {
double fuelNeeded = fuelConsumption * distance;
if ( fuelNeeded > fuelAmount ) {
std::cout << "Not enough fuel." << std::endl;
return;
}
fuelAmount -= fuelNeeded;
std::cout << "Car traveled " << distance << " miles." << std::endl;
}
void refill(double fuel) {
double maxRefillVolume = fuelCapacity - fuelAmount;
if ( fuel > maxRefillVolume ) {
std::cout << "Max fuel amount exceeded!"<< std::endl;
return;
}
fuelAmount += fuel;
std::cout << "Car was successfully refilled!" << std::endl;
}
void report() {
std::cout << "-- fuel capacity: " << fuelCapacity << std::endl;
std::cout << "-- fuel amount: " << fuelAmount << std::endl;
std::cout << "-- fuel consumption: " << fuelConsumption << std::endl;
}
};
int main() {
Car toyota(50.0, 50.0, 0.8);
toyota.report();
toyota.drive(40.0);
toyota.drive(30.0);
toyota.refill(100.0);
toyota.report();
toyota.refill(30.0);
toyota.report();
return 0;
}

--

--