360 likes | 433 Views
COMP 40: Machine Structure and Assembly Language Programming (Spring 2014). Abstraction, Modularity, Interfaces and Pointers. Noah Mendelsohn Tufts University Email: noah@cs.tufts.edu Web: http://www.cs.tufts.edu/~noah. We will weave together a story about.
E N D
COMP 40: Machine Structure and Assembly Language Programming (Spring 2014) Abstraction, Modularity, Interfaces and Pointers Noah Mendelsohn Tufts UniversityEmail: noah@cs.tufts.edu Web: http://www.cs.tufts.edu/~noah
We will weave together a story about • Abstraction, modularity, reuse, clean interfaces, information hiding • C Language Pointers Is it obvious these are related at all?
Software structures model real world objects and concepts • Integers • Students • Bank statements • Photographic images • Sound recordings • Etc. These things aren’t bits!! They don’t live in computers, but…
Software structures model real world objects and concepts • Integers • Students • Bank statements • Photographic images • Sound recordings • Etc. We build data structures that model them
Collections are especially interesting • Arrays of Integer temperature measurements • Queues of Students waiting to register for classes • Sorted lists of Bank statements • Etc.
Today we will focus on good ways of modeling Abstract Data Types like lists, sets, queues, etc. Doing that, we’ll learn a lot about programming with pointers and types in C
Key principles to watch for • Abstraction • Refers to the act of “pulling away from” something so that unimportant details are hidden”1 • Modularity & clean interfaces • Each module “does one thing well” 2 • Information hiding • Modules keep details of their internals secret • Generalization • When practical, each module or service should be as generally useful as possible 1 Prof. Mark Sheldon – COMP 11 Big Ideas 2Ken Thompson, co-inventor of Unix – The Unix Philosophy
What are the benefits of software like this? • Easier to use • Easier to reuse • Easier to replace • Easier to reason about correctness • Easer to test • Etc., etc.
E.g. methods in Hanson table.h Interfaces Interface Implementation Client E.g. your fgroups program E.g. implementation ofHanson Table_T
Interfaces Many different programs can re-use the interface and the implementation! Interface Implementation Client
Interfaces The implementation chooses a representation … NOT visible to the client Interface Implementation Client
Why reimplement?One might be small, one might be fast, etc.Bug fixesWe might figure out a better way next year Interfaces We can build different implementationswithout the client knowing Interface Implementation Client
Interfaces Interface Implementation To make this work we must……hide details of the implementation from the client! Client
Interfaces Interface Implementation To make this work we must……hide details of the client from the implementation! Client
Interfaces Interface Implementation Build interfaces that cleanly model the service or abstract data… Client
In your COMP 40 design documents, we expect you to carefully observe these distinctions… …your description of an interface should never mention implementation details …your description of use of an interface should nevermention implementation details.
E.g. methods in Hanson table.h Interfaces My client isn’t supposed to see internals of Hanson’s table, but Hanson needs to give us something….what can we use? Interface Implementation Client E.g. your fgroups program E.g. implementation ofHanson Table_T
E.g. methods in Hanson table.h Interfaces Q. What can Table_new return? A. A pointerto data you can’t look atYou will use this pointer to identify the new table Interface Implementation My_table = Table_new(… … …) Client I will show you two ways of doing this E.g. your fgroups program E.g. implementation ofHanson Table_T
Using void * pointers /* Declare the type Table_t to be a (void *) */ typedefvoid *Table_t; /* Define Table_new to return one of those (void *) */ Table_tTable_new(… … … …); • This is a pretty good solution: • Client can’t see details of what’s in Hanson’s structure • When Hanson gets the pointer back, he can assign it to a Table_Tit and use it
Client doesn’t know secret implementation structTable_T *table_ptr; Interface void *table_ptr; Implementation StructTable_t { …data declartions… } Client my_table = Table_new(… … …)
Using void * pointers /* Declare the type Table_t to be a (void *) */ typedefvoid *Table_t; /* Define Table_new to return a (void *) */ Table_tTable_new(… … … …); • This is a pretty good solution: • Client can’t see details of what’s in Hanson’s structure • When Hanson gets the pointer back, he can assign it to a Table_Tit and use it • But it doesn’t catch this mistake in the client… myTable = List_new(…); Table_put(myTable, … … …)
Tricky…we’re exposing the structure’s name, but not it’s contents…C calls this an incomplete structure. We can do better with incomplete structures /* Declare the type Table_t to be a (void *) */typedefstructTable_T *Table_t; You cannot declare a variable with an incomplete type. You can declare a variable that’s a pointer to an incomplete type!
Tricky…we’re exposing the structure’s name, but not it’s contents…C calls this an incomplete structure. We can do better with incomplete structures /* Declare the type Table_t to be a (void *) */typedefstructTable_T *Table_t; /* Define Table_new to return a ptr to incomplete*/Table_tTable_new(… … … …);
Client doesn’t know secret implementation structTable_T *table_ptr; Interface structTable_t *table_ptr; Implementation StructTable_t { …data declartions… } Client Client has incomplete declaration of the struct my_table = Table_new(… … …)
We can do better with incomplete structures /* Declare the type Table_t to be a (void *) */ typedefstructTable_T *Table_t; /* Define Table_new to return a (void *) */ Table_tTable_new(… … … …); • This is a better solution: • Client can’t see details of what’s in Hanson’s structure • When Hanson gets the pointer back, it just works • It does catch this mistake…you should figure out why! myTable = List_new(…); Table_put(myTable, … … …)
You’ve already seen some generalization int square(int n) { return n*n; } int square3() { return 3*3; } We don’t do this We do this! Generalize over input value Can we generalize over the typeof information?
We need to generalize over types List_of_students_new(…); List_of_cars_new(…); List_of_bank_stmts_new(…); List_new(…); We want this! We don’t want this Can we generalize over the typeof information? How do we declare the input to List_push()?(after all, its type could be anything)
Void * allows us to generalize over types The list will remember a pointer to anything. void List_push(List_T list, void *x); Hanson’s declaration for List_push structCar {char *brand; int weight;}; typedefstruct Car Car; List_Tmylist = List_list(NULL); Car *retrieved_car; Car mycar = {"ford", 2000}; mylist= List_push(mylist, &mycar); mylist= List_pop(mylist, (void **)&retrieved_car); List_free(&mylist); Any pointer can be passed to a void * parameter
Void * allows us to generalize over types void List_push(List_T list, void *x); IMPORTANT: Retrieved_car_p is already a pointer. Why do we have to pass the address of retrieved_car_p? Hanson’s declaration for List_push structCar {char *brand; int weight;}; typedefstruct Car Car; List_Tmylist = List_list(NULL); Car *retrieved_car; Car mycar = {"ford", 2000}; mylist= List_push(mylist, &mycar); mylist= List_pop(mylist, (void **)&retrieved_car); List_free(&mylist);
Void * allows us to generalize over types This generalization is known as universal polymorphism void List_push(List_T list, void *x); Hanson’s declaration for List_push struct Car {char *brand; int weight;}; typedefstruct Car Car; List_Tmylist = List_list(NULL); Car *retrieved_car; Car mycar = {"ford", 2000}; mylist = List_push(mylist, &mycar); mylist = List_pop(mylist, (void **)&retrieved_car); List_free(&mylist);
Review • Abstraction, modularity, reuse, clean interfaces, information hiding • C Language Pointers It should be clear now that theseare related