## Encapsulation and data hiding

Classes can be used for many purposes in scientific programming and computation. One of the most frequently encountered tasks is to represent mathematical functions that have a set of parameters in addition to one or more independent variables. These functions, together with all of their essential and auxiliary variables have to be frequently passed to other functions to perform some tasks. Implementing such problems using purely procedural programming tools that we have learned so far can lead to the development of an unsafe, unclean, and undesired codebase, which is not easy to work with either. To understand why and how this happens, consider the following scientific problem.

## A common programming challenge in numerical computing

Consider a function that takes in some parameters as input, for example, the equation of motion a stone when it is thrown upward in the air. The physics equation describing this motion is $y(t) = v_0t-\frac{1}{2}gt^2$. Physically speaking, this equation gives the position $y$ from the ground of the physical object stone, as a function of time. Therefore, in physics, $y$ is viewed as a function of $t$.

However, mathematically speaking, $y$ also depends on two other parameters, $v_0$ and $g$, although it is unnatural to view $y$ as a function of these parameters. One can therefore write $f(t;v_0g)$ to emphasize that $t$ is the independent variable, while $v_0$ and $g$ are parameters. Strictly speaking, $g$ is a fixed parameter (as long as the experiment is run on the surface of the earth), so only $v_0$ and $t$ can be arbitrarily chosen in the formula.

It would then be better to write $y(t;v_0)$. Here is an implementation of this function,

```
function height = getHeight(time,iniVel)
g = 9.81;
height = iniVel*time - 0.5*g*time^2;
end
```

This function gives the height of the projectile as a function of time. Now suppose you wanted to differentiate $y$ with respect to $t$ to obtain the velocity. You could write the following code to do so,

```
function derivative = getDerivative(func, x)
h = 1E-5;
derivative = (func(x+h) - func(x))/h;
end
```

But, here is the catch with this problem of differentiation. The `getDerivative`

function works with any function `func`

that takes **only** one argument. In other words, if we want to input `getHeight`

to `getDerivative`

, then we will have to redefine `getHeight`

to take only one argument. You may wonder why not change `getDerivative`

. For this simple problem, this could be a solution. But, with larger problems, you are more likely to use sophisticated routines and modules that have been already developed and many of these routines take a function as input that only has one input variable. This is quite often the case with high-performance integration routines.

One perhaps-bad solution to the above problem is to use **global variables**. The requirement is thus to define MATLAB implementations of mathematical functions of one variable with one argument, the independent variable,

```
function height = getHeightGlobal(time)
global iniVel;
g = 9.81;
height = iniVel*time - 0.5*g*time^2;
end
```

This function will work only if `iniVel`

is a global variable, initialized before one attempts to call the function. Here is an example call where `getDerivative`

differentiates y,

```
iniVel = 3;
derivative = getDerivative(@getHeightGlobal, 1)
```

The use of global variables is in general considered bad programming. Why global variables are problematic in the present case can be illustrated when there is a need to work with several versions of a function. Suppose we want to work with two versions of $y(t;v_0)$, one with $v_0=1$ and one with $v_0=5$. Every time we call `y`

, we must remember which version of the function we work with, and set `iniVel`

accordingly before the call,

```
global iniVel; iniVel = 1; r1 = getHeightGlobal(t)
global iniVel; iniVel = 5; r2 = getHeightGlobal(t)
```

*Another problem* is that variables with simple names like `iniVel`

, may easily be used as global variables in other parts of the program. These parts may change our `iniVel`

in a context different from the `getHeightGlobal`

function, but the change affects the correctness of the `getHeightGlobal`

function. In such a case, we say that changing `iniVel`

has **side effects**, i.e., **the change affects other parts of the program in an unintentional way**. This is one reason why a golden rule of programming tells us to **limit the use of global variables as much as possible**.

An alternative solution to the problem of needing two `iniVel`

parameters could be to introduce two `getHeight`

functions, each with a distinct `iniVel`

parameter,

```
function height = getHeightGlobal_1(time)
global iniVel_1; % initial velocity
g = 9.81;
height = iniVel_1*time - 0.5*g*time^2;
end
function height = getHeightGlobal_2(time)
global iniVel_2; % initial velocity
g = 9.81;
height = iniVel_2*time - 0.5*g*time^2;
end
```

Now we need to initialize `iniVel_1`

and `iniVel_2`

once, and then we can work with `getHeightGlobal_1()`

and `getHeightGlobal_2()`

. However, if we need $100$ `iniVel`

parameters, we need $100$ functions. This is tedious to code, error-prone, difficult to administer, and simply a really bad solution to a programming problem.

**So, is there a good remedy?** The answer is yes: the class concept solves all the problems described above.

### Class representation of a function

A class contains a set of variables (data) and a set of functions, held together as one unit. The variables are visible in all the functions in the class. That is, we can view the variables as “global” in these functions. You can also make many copies of a class.

Consider the function $y(t;v_0) = v_0t - \frac{1}{2}gt^2$. We may say that $v_0$ and $g$, represented by the variables `iniVel`

and `g`

, constitute the data. A MATLAB function, say `getValue(time)`

, is then needed to compute the value of $y(t;v_0)$ and this function must have access to the data `iniVel`

and `g`

, while `time`

is an argument. A programmer experienced with classes will then suggest collecting the data `iniVel`

and `g`

, and the function `getValue(time)`

, together as a **class**. Also, a class usually has another function, called **constructor** for **initializing the data**. The constructor is always named similar to the class-name. Every **class must have a name**, often **starting with a capital**, so we choose `ProjectileHeight`

as the name since the class represents a projectile motion. The next step is to implement this class in MATLAB. A complete class code `ProjectileHeight`

for our problem here would look as follows in MATLAB:

```
classdef ProjectileHeight
properties
g = 9.81;
iniVel; % initial velocity
end
methods (Access = public)
% This is the class constructor
function ProjectileHeightObject = ProjectileHeight(iniVel)
ProjectileHeightObject.iniVel = iniVel;
end
% Computes the height of the Projectile motion for a given time and initial velocity: iniVel
function height = getValue(ProjectileHeightObject,time)
height = ProjectileHeightObject.iniVel * time - 0.5 * ProjectileHeightObject.g * time^2;
end
end
end
```

**A class creates a new data type**, here of name `ProjectileHeight`

, so when we use the class to make objects, those objects are of type `ProjectileHeight`

. **All the standard MATLAB objects, such as lists, tuples, strings, floating-point numbers, integers, …, are built-in MATLAB classes**, and each time the user creates on these variable types, one instance of these classes are created by the MATLAB interpreter. A user-defined object class (like `ProjectileHeight`

) is usually called an **instance**. We need such an instance to use the data in the class and call the value function. The following statement constructs an instance bound to the variable name `MyProjectileHeight`

,

```
>> MyProjectileHeight = ProjectileHeight(100)
```

```
MyProjectileHeight =
ProjectileHeight with properties:
g: 9.8100
iniVel: 100
```

Seemingly, we *call the class ProjectileHeight as if it were a function*. Indeed,

`ProjectileHeight(3)`

is automatically translated by MATLAB to a call to the constructor method `ProjectileHeight()`

in class `ProjectileHeight`

. With the instance `MyProjectileHeight`

, we can compute the value of y(t=0.1;v_0=3) by the statement,```
>> height = MyProjectileHeight.getValue(1)
```

```
height =
95.0950
```

Note that the `ProjectileHeightObject`

input argument is dropped in the call to `getValue()`

method. To access functions and variables in a class, one must prefix the function and variable names by the name of the instance and a dot: the `getValue()`

function can be reached by `MyProjectileHeight.value`

, and the variables are reached as `MyProjectileHeight.iniVel`

and `MyProjectileHeight.g`

. One could, for example, print the value of `iniVel`

in the instance `getValue`

by writing,

```
MyProjectileHeight.iniVel
```

```
ans =
100
```

We have already introduced the term **instance** for the object of a class. **Functions** in classes are commonly called **methods**, and **variables (data)** in classes are called **data attributes**. Methods are also known as **method attributes**. For example, in our sample class `ProjectileHeight`

we have two methods or method attributes, `ProjectileHeight()`

and `getValue()`

, two data attributes, `iniVel`

and `g`

. Note that the names of attributes can be chosen freely, just as names of ordinary MATLAB functions and variables. However, **the constructor must have the same name as the name of the class, otherwise, it is not automatically called when new instances are created**. You can do whatever you want in whatever method, but it is a common convention to **use the constructor for initializing the variables of an instance of a class**.

## Calling object methods from other functions

So far, we have an object-oriented implementation of our ProjectileHeight motion. Now, going back to the original differentiation problem, if we want to be able to differentiate the height with respect to time using the function `getDerivative()`

, we will have to pass `MyProjectileHeight`

object in its entirety to `getDerivative()`

,

```
function derivative = getDerivativeOOP(FuncObj, x)
h = 1E-5;
derivative = (FuncObj.getValue(x+h) - FuncObj.getValue(x))/h;
end
```

```
>> MyProjectileHeight = ProjectileHeight(100) % create object with initial velocity 100 (m/s)
```

```
MyProjectileHeight =
ProjectileHeight with properties:
g: 9.8100
iniVel: 100
```

```
>> derivative = getDerivativeOOP(MyProjectileHeight,1) % compute derivative at time = 1 (s)
```

```
derivative =
90.1900
```