Knowledge base

IT is a great and exciting world to be in.
All who have passion for it will understand why we have created these pages.
Here we share our technical knowledge with you.
ProgrammingAICloudManagementMobileDB & AnalysisSafetyOtherArchitectureTips

OOP #1 - Class, Object, Pointer

Libor Bešenyi (Solution Architect)

Object-oriented programming, despite its simplicity, is not readily explainable to beginners. They make many errors despite the fact that they work under the guidance of experienced programmers or professional books. This article does not aim to explain the basics of OOP better, it rather aims to provide a less academic interpretation oriented on practice.

First of all, we need to understand what is a class and what is an object. A class is actually something like a "form" of an object. If we want to make cookies, we need only one cutter, but we can make more cookies with it. In this sense, class is the cutter and cookie is the object.

Whenever I need to solve a more complicated problem, I try to simulate it on an easy application. I usually create WinForms application with one click and I program the logic on a OnClick event. I'll leave the choice of a process to you.

Let’s have a look at an example of a class:

// *************************************************************************
// *** Class **************************************************************
// *************************************************************************
public class Class
{
} // public class Class

How do we create an object out of this – seemingly empty - class? Simply:

Class class = new Class();

Hence, Class (uppercase „T“) is a class and object is a class (lowercase „t“).  Why is an object a cookie? Because we can create one class X-times (as a form):

Class class = new Class();
Class class2 = new Class();
Class classMine = new Class();

As we can see, we are changing the name of the object, but the "prescription" (the form) remains the same. So how do we know that these objects are different if they use the same class? We will show you in a bit but let’s get a bit of background first. If we make cookies, the cutter will serve us only for the very creation – it no longer plays a role in the life cycle of a cookie (when we eat it, we do not eat the cutter as well; the cutter does not break when a cookie breaks).  Therefore, we need to approach the classes and objects in similar way.

The object is something real, something we can manipulate and the cutter is only a kind of "prescription" that does not have much in common with the object itself (only certain attributes were defined thanks to it  - like the shape of cookies). Every single cookie can be therefore modified independently from the cutter (e.g.  we can draw a different pattern on every piece of gingerbread – the cutter in the shape of a star is a class, every single star is the so called instance of a cutter - the object). The fact that the class is not operational (it only helps with the definition) means that it is static.

Let's add something that we can "draw" on to the class (some surface):

// *************************************************************************
// *** Class **************************************************************
// *************************************************************************
public class Class
{
    // ---------------------------------------------------------------------
    public string Text;
} // public class Class

To showcase how the templates (cutters) are independent (or how classes are independent from objects) we will create a special text for each instance:

private void button1_Click(object sender, EventArgs e)
{
    Class class = new Class();
    class.Text = "Text A";

    Class class2 = new Class();
    class2.Text = "Text 2";

    Class classMoja = new Class();
    classMoja.Text = "Text III.";

    MessageBox.Show(class.Text);
    MessageBox.Show(class2.Text);
    MessageBox.Show(classMoja.Text);
}

As we can see, the class with a capital C does not change anything. However, if we create N instances, these are able to keep their data. The class itself knows that it can contain the string "Text" – however, it does not control the content. It is controlled by an instance of the class. Each instance has therefore a variable "Text", but the content of the variable is no longer within competence of the given object!

Pointer arithmetic

Class thus prescribes how the object should look – we will learn why it's so important later. But now we need to understand the concept of a pointer. The pointer is actually an object (a cookie). Memory contains only an address, where are the data of a class that we can reconstruct.

The fact that there is a class as a static object and an object as a "live" instance means that the memory contains data of the object in the form prescribed by the class. We can therefore imagine that, for example, if you have a class with two strings and a string has 5 characters, the memory is then occupied by 2x5 characters. Each object is actually only the address number, where the class is in the memory and, of course, it defines the class, so that we know how to access this memory (where the object ends, where the particular data of the object is, etc.).

0

1

2

3

4

5

6

8

8

9

10

11

12

13

14

15

16

17

18

19

$

A

 

A

T

E

X

T

 

T

e

x

T

2

 

-

 

@

T

E

Thus, if there were simplified rules mentioned above, the object would only be the address that would refer to number 4. If the class was as follows:

// *************************************************************************
// *** Class **************************************************************
// *************************************************************************
public class Class
{
    // ---------------------------------------------------------------------
    public string Text1;
    public string Text2;
} // public class Class

... then the instance of the given class would be as follows (it is a very simplified view):

private void button1_Click(object sender, EventArgs e)
{
    Class class = new Class();
    class.Text1 = "Text";
    class.Text1 = "Text2";
}

As we can see, the actual variable name does not matter. The program (translator) knows it has two types (string) and if we assume that the string can have maximum of 5 characters, it reserved appropriate space in the memory (note address 8 – it is empty, although it is not defined as a value).

The instance (object) in this case is only the address of the data in the memory that is to be "translated" according to a particular template (class). Thus, if the pointer points to memory address 4, and I know that this is the instance of class Class, then it is obvious that we should "seek" two strings, and since they each have 5 characters, the class is allocated in the memory from address 4 .. 13.

That is important to note, people mostly make a mistake at this point (even though it's basically the cornerstone in understanding OOP). So what is up? Let's examine the first part of the syntax of creating an object from a class:

Class class = ...

What does it mean? It is necessary to create an instance named "class" of class "Class". Thus, we know that if it looks like in the last example (two strings Text1 and Text2), while the string has 5 characters, we must allocate 10 bits in memory.

The right side determines whether to create a new instance (allocate space and assign a new address to the variable), or it is left blank (Null, nil) or allocate it to an existing address. If we have two instances in the program created as follows:

Class classA = new Class();
classA.Text1 = "Text";
classA.Text2 = "Text2";

Class classB = new Class();
classB.Text1 = "bla";
classB.Text2 = "bla";

..memory looks as follows:

0

1

2

3

4

5

6

8

8

9

10

11

12

13

14

15

16

17

18

19

T

E

t

 

T

E

x

2

b

L

a

 

 

B

a

   

While classA points to address 0 and classB points to address 10. Thus, the variable itself is actually just an address (pointer) and it points to a specific memory location. Nothing more, nothing less. We know how to enforce the allocation of values in C#:

private void button1_Click(object sender, EventArgs e)
{
    Class classA = new Class();
    classA.Text1 = "Text";
    classA.Text1 = "Text2";

    Class classB = new Class();
    classB.Text1 = "bla";
    classB.Text1 = "bla";

    classB = classA;
    MessageBox.Show(classB.Text1);
}

This causes that the object classB points to the same address in the memory. Now beware: By allocating one variable to another, we didn’t allocate its content, only the address !!! It is different in comparison to ordinal types:

string nieco = "Nieco";
string niecoIne = "Ine";

niecoIne = nieco;
niecoIne += "Text";

MessageBox.Show(nieco);
MessageBox.Show(niecoIne);

In case of ordinal types, the value is "transferred." The address is, however, the value, and therefore, if two pointers point to the same memory, they do operations on the same object!!!

private void button1_Click(object sender, EventArgs e)
{
    Class classA = new Class();
    classA.Text1 = "TextA";
    MessageBox.Show(classA.Text1);

    Class classB = new Class();
    classB.Text1 = "TextC";
    MessageBox.Show(classB.Text1);

    classB = classA;
    MessageBox.Show(classB.Text1);

    classB.Text1 = "BLA";
    MessageBox.Show(classB.Text1);
    MessageBox.Show(classA.Text1);
}

Here, I would like to note that in the above example, we have forever lost the reference to the memory of the second object, they both refer to the same location (memory is not sequential, it can be allocated randomly – we will get back to it later when we show the so called memory leaks).

I would like to stop at pointer arithmetic as we must clarify this! We know what’s it like with the values transmitted in ordinal types. Consider the auxiliary method:

// ---------------------------------------------------------------------
private void button1_Click(object sender, EventArgs e)
{
    string text = "Hello World";            
    MessageBox.Show("button1_Click(): " + text);

    AddItem(text);

    MessageBox.Show("button1_Click(): " + text);
}

// ---------------------------------------------------------------------
public void AddItem(string string)
{
    string += "_1";

    MessageBox.Show("AddItem(): " + string);
}

The output is clear:

button1_Click(): Hello World

AddItem(): Hello World_1

button1_Click(): Hello World

Why is this so? Because in this case we transfer value into the method. If we wanted to change it in the method, we would have to send it - not as a value but as a pointer (yes, even ordinal types shall refer to locations in memory - an advantage for those who learnt e.g. in C language). It is surely obvious to everyone how this can be achieved in C# (we add REF):

 // ---------------------------------------------------------------------
 private void button1_Click(object sender, EventArgs e)
 {
    string text = "Hello World";            
    MessageBox.Show("button1_Click(): " + text);

    AddItem(ref text);

    MessageBox.Show("button1_Click(): " + text);
}

// ---------------------------------------------------------------------
public void AddItem(ref string string)
{
    string += "_1";

    MessageBox.Show("AddItem(): " + string);
}

The output then is:

button1_Click(): Hello World

AddItem(): Hello World_1

button1_Click(): Hello World_1

                 As is the case with objects, we already mentioned. Objects are implicitly transferred by reference (pointer), and thus only address is transferred at all times. So use of "ref" in this case is essentially a deep misunderstanding (sounds weird, but actually it can be seen). So we get exactly the same output in this example of the classes too:

// ---------------------------------------------------------------------
private void button1_Click(object sender, EventArgs e)
{
    Class class = new Class();
    class.Text1 = "Hello World";

    MessageBox.Show("button1_Click(): " + class.Text1);

    AddItem(class);

    MessageBox.Show("button1_Click(): " + class.Text1);
}

// ---------------------------------------------------------------------
public void AddItem(Class ubovolnaInstanciaTriedy)
{
    ubovolnaInstanciaTriedy.Text1 += "_1";

    MessageBox.Show("AddItem(): " + ubovolnaInstanciaTriedy.Text1);
}

And why do I mention it here? Because REF in OOP would mean that we can change the address in the method! Therefore, the use of REF on an inappropriate location can largely confuse the source code (as the programmer may expect  more "invasive" change).

"C-users" once again have the advantage. If the object itself is a pointer, what is the reference to the pointer then? Normally, it is called a pointer on a pointer: the address (pointer) must be located somewhere in the memory (e.g. as a number). Reference to the pointer is actually a link to this location, it is usually quite dangerous (but sometimes necessary) - we will talk about it more in the next chapter.

Find out more

Programming

Quick start

1
Contact
Contact us for a free consultation on your business needs!
2
Analysis
After the discussion we will perform mapping of the processes and analyse the current state.
3
Proposal
You will receive variety of scenarios to choose from discribing different ways how to solve your issue.
Contact us