Monday, 19 April 2021

Modern day Record Handling with C++

Record Handling analysis

Record Handling by C.A.R Hoare introduced the notion of objects as records.

Key features

  • Garbage collection through reference counting.
  • References for compositing functional relationships.
  • Dynamic allocation so objects can outlive their block.
  • Create and Destroy procedures for creating objects (anywhere in the program) and removing them.

C++

In modern C++ the record handling features above are possible.

Feature C++ Java
Garbage collection std::shared_ptr Built into the JVM.
References std::shared_ptr All objects are reference types.
Dynamic allocation
  • Per class custom allocator to prevent fragmentation
  • use of 'new' wrapped in a std::shared_ptr
All objects are dynamically allocated.
Create and destroy procedures 'new' and 'delete' 'new' provided but no explicit destroy procedure.

Example


Notes

C++ is prefereable to Java because not all objects require the record handling features. A large portion of programming does not deal with true "objects" in the sense that record handling denotes, therefore by using C++ and C we can efficiently control the machine and only optionally invoke the record handling features when required.

Friday, 16 April 2021

OOP without the heap

Safety critical software standards forbid dynamic memory however OOP is desirable when designing an embedded system. OOP can be used without dynamic memory by preallocating space for the objects at a suitable location and creating references to them. References are mandatory for OOP however the heap can be avoided.

Saturday, 20 March 2021

The difference between class and object.

 The difference between class and object is subtle and misunderstood frequently. It is important to understand the difference in order to write cleaner class heirachies. 

First, the word "Object" is taken from Philosophy that is used to describe something that exists in the world around you at this very minute in time. For example; the computer in front of you, the keyboard you are using and yourself. 

Secondly, classes represent groups of these objects. A class called Keyboard represents all keyboard objects.

Class keyboard and its objects

 

Hopefully this has shown you the difference between an object and a class in terms of philosophy so that you know what should be a class and what shouldn't.

Saturday, 13 March 2021

Single inheritance in C

Inheritance is a powerful mechanism for code organization, unfortunatly the class concept is not present in the C language. Therefore, there is a need for the inheritance mechanism in C where C++ is not available. Inheritance is an extremely complex mechanism, we can only hope to capture a small slice of its features in C without breaking the C language too much. The solution is to make two structures compatible if a pointer to the derived type is upcasted to the base type, therefore we can use the derived type in the base type's procedures.

 

typedef struct { 

    float originX, originY;

} Shape;

void SetOrigin(Shape* shape, float x, float y); 

float GetOriginX(Shape* shape); 

float GetOriginY(Shape* shape);

 

typedef struct { 

    Shape base; // this allows Circle* to represent Shape*

    float radius;

} Circle; 

void SetRadius(Circle* circle);

Thursday, 3 December 2020

OOP - Recovering lost class types

 Normally casting is used to convert classes to other classes, however this operation can break the type system.

For example, a "List" may use the class "ListItem". And the "ListItem" is then inherited by the "Item" class. So we may store "Item" classes in the "List" class.

Using casting we could recover the "Item" class from the "ListItem" class like this:

 

ListItem* ptr = list.front();

Item* item = (ListItem*)ptr;

 

However here, we have over-ruled the type system to enforce the cast from ListItem to Item. We need a way to perform this operation without breaking the type system rules.

 

 

 

 

One method is to store the type information in the base class, to be used later to reconstruct the derived class is, for example:

class ListItem {

public:

    bool isItem = false; // stored type information

    bool isLinkedItem = false;

}

 

class Item : public ListItem {

public: 

    Item(ListItem* listItem) {

        // reconstruct this class using p_list_item details    

    }

 

    // new method declared not accessible in ListItem class.

    void Print() {

        printf("item");

    }

}


ListItem* listItem = list.front();

if (listItem->isItem) {                           // check type information

    Item* item = new Item(listItem);              // reconstruct

    list.pop();

    delete listItem;                                  // delete old object

} else if (ptr->isLinkedItem) {

    // .etc

}


This is more desirable since the type system is preserved, which means that our code can be statically verified by the compiler. Also, it has an effect on how the classes are designed. Since now our type information is being manually specified, we can potentially perform more complicated operations depending on the base types-type members, for example:

if (listItem->isItem && !listItem->isLinked && listItem->isBack) { // reconstruct // }


Friday, 13 November 2020

Abstraction function, representation invariant

Abstraction Function & Rep invariant

The abstraction functions map values in a class to the abstract concept's required values. The representation invariants are those values that satisfy the abstraction function. By asserting the abstraction function we create the link (abstraction) from ints and string to our concept. This can be seen as giving the class meaning.

The abstraction funtion is like a filter that only allows values past which correctly describe the abstract concept.

 

http://web.mit.edu/6.005/www/fa14/classes/09-af-ri-equality/
Figure 1 - RatNum ADT
 

Example

Below ZeroNumber is the concept we want to create. We represent it with a float however the concept requires that it only represents the number 0. Therefore we assert the abstraction function on the inValue and discard any values which are not rep invariants, this results in our classes concept (of being zero) being enforced.

class ZeroNumber {
public:
    ZeroNumber(float inValue) {
        assert(inValue == 0.0f);     (2. Assertion for rep invariants)
        value = inValue;
    }
private:
    float value;  (1. Representation)
}

The abstraction function here is that the ZeroNumber class must be a number that can only be 0.

The rep invariants here are all values of (inValue) that are 0.0f.  In order for abstration function to hold the assertion (2) must hold since only rep invariants are allowed.

References

  • http://web.mit.edu/6.005/www/fa14/classes/09-af-ri-equality/
  • Object-oriented Software Construction, 1st Edition Bertrand Meyer

Tuesday, 10 November 2020

Object interface design - telling it to do something vs doing something to it

 An object represents a concept otherwise known as a "thing" or noun. Traditionally, we're taught that you can create an object then tell it what to do, however, this design (coming from Alan Kay) actually results in a mess of global state (which is the usual complaint about OOP). A more appropriate view is a little more complicated, we can create an object but we must define what we can do TO it.

For example you can Squeeze an Orange, therefore the object Orange has the Squeeze method. Traditionally it would be modelled as Person.Squeeze(Orange) however, here you aren't actually doing something TO the person object you are telling the person to do SOMETHING.

Modern day Record Handling with C++

Record Handling analysis Record Handling by C.A.R Hoare introduced the notion of objects as records. Key features Garbage collection t...