40
Abstraction, Modularity, Interfaces and Pointers Original slides by Noah Mendelsohn, including content from Mark Sheldon, Noah Daniels, Norman Ramsey COMP 40: Machine Structure and Assembly Language Programming

Abstraction, Modularity, Interfaces and Pointers Original slides by Noah Mendelsohn, including content from Mark Sheldon, Noah Daniels, Norman Ramsey COMP

Embed Size (px)

Citation preview

Abstraction, Modularity, Interfaces and Pointers

Original slides by Noah Mendelsohn, including content from Mark Sheldon, Noah Daniels, Norman Ramsey

COMP 40: Machine Structure and

Assembly Language Programming

© 2010 Noah Mendelsohn

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?

© 2010 Noah Mendelsohn

Abstractand

Concrete Types

© 2010 Noah Mendelsohn

Software structures model real world objects and concepts

Integers

Students

Bank statements

Photographic images

Sound recordings

Etc.

4

These things aren’t bits

They don’t live in computers, but…

© 2010 Noah Mendelsohn

Software structures model real world objects and concepts

Integers

Students

Bank statements

Photographic images

Sound recordings

Etc.

5

We build data structures that model them

© 2010 Noah Mendelsohn

Collections are especially interesting

Arrays of Integer temperature measurements

Queues of Students waiting to register for classes

Sorted lists of Bank statements

Etc.

6

© 2010 Noah Mendelsohn7

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

© 2010 Noah Mendelsohn

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

– This makes them more modular: why?

Generalization– When practical, each module or service should be as generally useful as

possible

8

1 Prof. Mark Sheldon – COMP 11 Big Ideas 2 Ken Thompson, co-inventor of Unix – The Unix Philosophy

© 2010 Noah Mendelsohn

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

Easier to maintain

Etc., etc.

9

© 2010 Noah Mendelsohn

AbstractionClean Interfaces

Information Hiding

© 2010 Noah Mendelsohn

Interfaces (Recall picture from Comp 11)

11

Inte

rface

ImplementationClient

E.g. your fgroups program

E.g. implementation ofHanson Table_T

E.g. methods in Hanson table.h

© 2010 Noah Mendelsohn

Interfaces

12

Inte

rface

ImplementationClient

Many different programs can re-use the interface and the implementation!

© 2010 Noah Mendelsohn

Interfaces

13

Inte

rface

ImplementationClient

The implementation chooses a representation … NOT visible to the client

© 2010 Noah Mendelsohn

Interfaces

14

Inte

rface

ImplementationClient

We can build different implementations without the client knowing

Why reimplement?

One might be small, one might be fast, etc.

Bug fixes

We might figure out a better way next year

© 2010 Noah Mendelsohn

Information Hiding

© 2010 Noah Mendelsohn

Interfaces

16

Inte

rface

ImplementationClient

To make this work we must…

…hide details of the implementation from the client!

© 2010 Noah Mendelsohn

Interfaces

17

Inte

rface

ImplementationClient

To make this work we must…

…hide details of the client from the implementation!

© 2010 Noah Mendelsohn

Interfaces

18

Inte

rface

ImplementationClient

Build interfaces that cleanly model the service or abstract data…

© 2010 Noah Mendelsohn19

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 never mention implementation details.

© 2010 Noah Mendelsohn

Using Pointers to Represent Objects

andKeep Secrets

© 2010 Noah Mendelsohn

Most pointer declarations include type of the referent

21

#include <stdio.h>#include <stdlib.h>

intmain(int argc, char *argv[]){

(void)argc;(void)argv;

int x = 3;int y;

int *ptr; ptr = &x;

y = *ptr;

printf("y = %d\n", y);

exit(EXIT_SUCCESS);}

Pointer to an integer

© 2010 Noah Mendelsohn

Void pointers are to unknown type

23

#include <stdio.h>#include <stdlib.h>

intmain(int argc, char *argv[]){

(void)argc;(void)argv;

int x = 3;int y;

void *ptr; ptr = &x;

y = *ptr;

printf("y = %d\n", y);

exit(EXIT_SUCCESS);}

Compile error!!

Can’t assign value of unknown type (*ptr) to integer y.

void *

Compiler knows it’s a pointer.

Compiler does not know what type it points to.

© 2010 Noah Mendelsohn

But we can tell the compiler the type

24

#include <stdio.h>#include <stdlib.h>

intmain(int argc, char *argv[]){

(void)argc;(void)argv;

int x = 3;int y;

void *ptr; ptr = &x;

y = *((int *)ptr);

printf("y = %d\n", y);

exit(EXIT_SUCCESS);}

FIXED!

We can use a cast (in this case

((int *)ptr)

to tell the compiler the type it should assume

© 2010 Noah Mendelsohn

Void pointers let us do some very important things!

Make our code more general – work with any type of data

Keep secrets

25

But why would we want to keep secrets?

© 2010 Noah Mendelsohn

Interfaces

26

Inte

rface

ImplementationClient

E.g. your fgroups program

E.g. implementation ofHanson Table_T

E.g. methods in Hanson table.h

My client isn’t supposed to see internals of Hanson’s table, but Hanson needs to give us something….what can we use?

© 2010 Noah Mendelsohn

Interfaces

27

Inte

rface

ImplementationClient

E.g. your fgroups program

E.g. implementation ofHanson Table_T

E.g. methods in Hanson table.h

My_table = Table_new(… … …)

Q. What can Table_new return?

I will show you two ways of doing this

A. A pointer to data you can’t look at

You will use this pointer to identify the new table

© 2010 Noah Mendelsohn

Using void * pointers

28

/* Declare the type Table_t to be a (void *) */typedef void *Table_t;

/* Define Table_new to return one of those (void *) */Table_t Table_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_T and use it

© 2010 Noah Mendelsohn

Client doesn’t know secret implementation

29

Inte

rface

ImplementationClient

my_table = Table_new(… … …)

Struct Table_t { …data declartions…}

struct Table_T *table_ptr;

void *table_ptr;

© 2010 Noah Mendelsohn

Using void * pointers

30

/* Declare the type Table_t to be a (void *) */typedef void *Table_t;

/* Define Table_new to return a (void *) */Table_t Table_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_T and use it• But it doesn’t catch this mistake in the client…

myTable = List_new(…);Table_put(myTable, … … …)

© 2010 Noah Mendelsohn

We can do better with incomplete structures

31

typedef struct Table_T *Table_t;

Tricky…we’re exposing the structure’s name, but not it’s contents…C calls this an incomplete structure.

You cannot declare a variable with an incomplete type.

You can declare a variable that’s a pointer to an incomplete type!

Declare the type Table_t to be a pointer to a struct whose contents are unspecified:

© 2010 Noah Mendelsohn

We can do better with incomplete structures

32

typedef struct Table_T *Table_t;

/* Table_new returns ptr to incomplete struct */Table_t Table_new(… … … …);

Tricky…we’re exposing the structure’s name, but not it’s contents…C calls this an incomplete structure.

© 2010 Noah Mendelsohn

Client doesn’t know secret implementation

33

Inte

rface

ImplementationClient

my_table = Table_new(… … …)

Struct Table_t { …data declartions…}

struct Table_T *table_ptr;

struct Table_t *table_ptr;

Client has incomplete

declaration of the struct

© 2010 Noah Mendelsohn

We can do better with incomplete structures

34

typedef struct Table_T *Table_t;

Table_t Table_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, … … …)

© 2010 Noah Mendelsohn

Generalization

© 2010 Noah Mendelsohn

You’ve already seen some generalization

36

int square3() {

return 3 * 3;}

We don’t do this

int square(int n) {

return n * n;}

We do this!

Generalize over input value

Can we generalize over the type of information?

© 2010 Noah Mendelsohn

We need to generalize over types

37

List_of_students_new(…);List_of_cars_new(…);List_of_bank_stmts_new(…);

We don’t want this

List_new(…);

We want this!

How do we declare the input to List_push()?(after all, its type could be anything)

Can we generalize over the type of information?

© 2010 Noah Mendelsohn

Void * allows us to generalize over types

38

void List_push(List_T list, void *x);

Hanson’s declaration for List_push

The list will remember a pointer to anything.

struct Car {char *brand; int weight;}; typedef struct Car Car;List_T mylist = 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 pointer-to-void parameter

© 2010 Noah Mendelsohn

Void * allows us to generalize over types

39

void List_push(List_T list, void *x);

Hanson’s declaration for List_push

struct Car {char *brand; int weight;}; typedef struct Car Car;List_T mylist = 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);

IMPORTANT:Retrieved_car_p is already a pointer. Why do we have to pass the address of retrieved_car_p?

© 2010 Noah Mendelsohn

Void * allows us to generalize over types

40

void List_push(List_T list, void *x);

Hanson’s declaration for List_push

struct Car {char *brand; int weight;}; typedef struct Car Car;List_T mylist = 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);

This generalization is known as universal polymorphism

© 2010 Noah Mendelsohn

Review

Abstraction, modularity, reuse, clean interfaces, information hiding

C Language Pointers

It should be clear now that these are related