What is object orientation?
- Combination of data and functions
- f(o) is the same thing as o.f()
- We've always combined data and functions
- Encapsulation, Inheritance, Polymorphism
Encapsulation
- Private and public class fields/methods
- Can draw borders between disparate parts of the application
- Limits consideration of what can affect one part to its interface
- Could do this in c
- Headers define the interface, .c files contain the implementation
- Details left out of the header aren't available to other code
- point.h
struct Point;
struct Point * makePoint(double x, double y);
double distance(struct Point *p1, struct Point *p2);
- point.c
#include "point.h"
#include <stdlib.h>
#include <math.h>
struct Point {
double x,y;
}
struct Point *makePoint(double x, double y) {
struct Point *p = malloc(sizeof(struct Point));
p->x = x;
p->y = y;
return p;
}
double distance(struct Point *p1, struct Point *p2) {
double dx = p1->x - p2->x
double dy = p1->y - p2->y;
return sqrt(dx*dx, dy*dy);
}
- The Point struct is forward declared in the header, but the actual definition is in the implementation
- Usage code including the header knows
- There is some data with an unknown format called Point
- Some functions that will take the type pointer to Point
- Usage code does not know the size or contents
- Can't use as a value type, only pointer
- This is called an opaque pointer
- Note however, that the struct definition from the implementation could be copied into the usage code to tell it about the format
- C++ added object orientation
- Implementation requires data members to be declared in the header
- This breaks encapsulation
- While the compiler will prevent access to those variables usage code still needs to read it
- Java and C# remove the distinction between interface and implementation files further weakening encapsulation
- Hard to say that OO depends on strong encapsulation
Inheritance
- Inheritance is the redeclaration of a group of variables and functions within an enclosing scope
- Can do this in c
- namedPoint.h
struct NamedPoint;
struct NamedPoint *makeNamedPoint(double x, double y, char *name);
void setName(struct NamedPoint *np, char *name);
char *getName(struct NamedPoint *np);
- namedPoint.c
#include "namedPoint.h"
#include <stdlib.h>
struct NamedPoint {
double x,y;
char *name;
}
struct NamedPoint *makeNamedPoint(double x, double y, char *name) {
struct NamedPoint *p = malloc(sizeof(struct NamedPoint));
p->x = x;
p->y = y;
p->name = name;
return p;
}
void setName(struct NamedPoint *np, char *name) {
np->name = name;
}
char *getName(struct NamedPoint *np) {
return np->name;
}
- main.c
#include "point.h"
#include "namedPoint.h"
#include <stdio.h>
int main(int ac, char **av) {
struct NamedPoint *origin = makeNamedPoint(0.0, 0.0, "origin");
struct NamedPoint *upperRight = makeNamedPoint(1.0, 1.0, "upperRight");
printf("distance=%f\n",
distance(
(struct Point*) origin,
(struct Point*) upperRight
)
);
}
- NamedPoint starts with the same data members as Point with the same offsets
- So a pointer to NamedPoint can act as a pointer to Point
- Common practice in C
- Multiple inheritance is harder
- Had to cast NamedPoint to Point - an OO language would do this automatically
- OO makes inheritance a lot nicer
Polymorphism
struct FILE {
void (*open)(char *name, int mode);
void (*close)();
int (*read)();
void (*write)(char);
void (*seek)(long index, int mode);
}
- FILE is a struct that contains a bunch of function pointers - an interface
- This can be implemented by a device driver to allow any function that takes a FILE struct to perform these operations
#include "file.h"
void open(char *name, int mode) {}
void close() {}
int read() {}
void write(char c) {}
void seek(long index, int mode) {}
struct FILE console = {open, close, read, write, seek};
extern struct FILE *stdin;
int getchar() {
return stdin->read();
}
- Object orientation in C++ is just a virtual table at the start of the object that looks like the FILE for all the virtual methods
- Polymorphism is just pointers to functions
- OO made it safer and more convenient
- Need to initialize all the pointers correctly
- Need to make all calls through the pointers
- Bugs can be hard to find
- OO imposes discipline on indirect transfer of control
Power of polymorphism
- Have a copy program which copies from an input device to an output device
- Want to add devices for handwriting recognition and speech synthesis
- With polymorphism don't even need to recompile the program
- It just calls interfaces of a particular form and knows nothing about the details
- UNIX made devices plugins - was common to want to perform the same operations on different devices
- Decks of cards, magnetic tape
- Most programmers did not extend this to their own code - pointers to functions are dangerous
Dependency inversion
- Before OO
- The main function calls higher level functions
- Higher level functions call mid level functions
- Mid level functions call low level functions
- Source dependencies, imports follow this flow
- Main has to import the higher level functions so it can call them
- Flow of control dictated by behaviour
- Source dependencies dictated by flow of control
- Polymorphism
- Can import an interface instead of the concrete implementation
- Can then use any concrete implementation at runtime
- Architects have complete control over the direction of dependencies in the system

- Can rearrange dependencies so that database and UI depend on business rules
- Can then compile into separate components or deployment units
- Business rules do not depend on UI and database, they can be updated and deployed separately
- Independent deployability: only the changed component needs to be reseployed
- Independent developability: modules which can be deployed separately can be developed separately by different teams
Conclusion
- OO is the ability to gain control of the direction of every dependency in the system through polymorphism
- Allows the creation of a plugin architecture which allows higher level components to be independent of lower level ones
- The lower level components can also be developed and deployed independently of the higher level