77
Building Abstractions with Data (Part 1) CS 21a: Introduction to Computing I First Semester, 2013-2014

Building Abstractions with Data (Part 1)

  • Upload
    rupert

  • View
    45

  • Download
    0

Embed Size (px)

DESCRIPTION

Building Abstractions with Data (Part 1). CS 21a: Introduction to Computing I First Semester, 2013-2014. Last Time…. Procedural Abstraction Creating layers of abstraction for algorithms. Today…. Data Abstraction Creating layers of abstraction for data. Outline. The Notion of Types - PowerPoint PPT Presentation

Citation preview

Page 1: Building Abstractions with Data  (Part 1)

Building Abstractions

with Data (Part 1)

CS 21a: Introduction to Computing I

First Semester, 2013-2014

Page 2: Building Abstractions with Data  (Part 1)

Last Time…►Procedural Abstraction►Creating layers of abstraction for

algorithms

Page 3: Building Abstractions with Data  (Part 1)

Today…►Data Abstraction►Creating layers of abstraction for data

Page 4: Building Abstractions with Data  (Part 1)

Outline►The Notion of Types►Abstractions with Data Types►Same Type, Different Implementations

Page 5: Building Abstractions with Data  (Part 1)

The Notion of Types►“G” is a letter, but not a number.►“800-9000” is a telephone number,

but “[email protected]” is an e-mail address.

►What you’re sitting on is a chair, not a table (hopefully).

►You are a person, not a dog (don’t let your significant other change that).

Page 6: Building Abstractions with Data  (Part 1)

The Notion of Types►Any value has a type.►Any piece of data has a data type.►Why is this important?

Page 7: Building Abstractions with Data  (Part 1)

Type Safety►There are procedures that can only be

meaningfully carried out if the input data is of a certain type.►Examples:

►Sitting should be done on chairs, (maybe occasionally on tables if you have good reasons), but not on candles.

►Squaring should be done on numbers, but not on words.

Page 8: Building Abstractions with Data  (Part 1)

Type Safety►Helps catch programming errors early►No accidental squaring of words and

using the result as a prescribed amount of medicine.

Page 9: Building Abstractions with Data  (Part 1)

Which Assignments Are Allowed?

int a = 16;

double b = 18.5;

a = b;

double c = 18;

a = c;

c = a;

Page 10: Building Abstractions with Data  (Part 1)

Type Safety in Variablesint a = 16;

double b = 18.5;

a = b; // not allowed

double c = 18; // allowed: integers are real numbers

a = c; // still not allowed

c = a; // allowed: integers are real numbers

Page 11: Building Abstractions with Data  (Part 1)

Type Safety in Variablesint a = 16;

double b = 18.5;

a = b; // not allowed

double c = 18; // allowed: integers are real numbers

a = c; // still not allowed

c = a; // allowed: integers are real numbers

Type specifiers put a restriction on what values a variable can hold.

Page 12: Building Abstractions with Data  (Part 1)

Type Safety in Proceduresstatic int square(int x){

return x*x;} parameter type specifier

return type specifier

return value must be of correct type

Page 13: Building Abstractions with Data  (Part 1)

Will This Work?int a = square("Hello");

Page 14: Building Abstractions with Data  (Part 1)

Will This Work?int a = square("Hello");

square expects integer arguments. Design by contract, and propagate type safety down the barriers of abstraction: square needs to ensure that it’s given an integer, because it will use that argument in a * operation, which also requires its operands to be numbers. The user of square must therefore follow this restriction and only pass an integer argument.

Page 15: Building Abstractions with Data  (Part 1)

How About This?int a = square(3);

Page 16: Building Abstractions with Data  (Part 1)

How About This?int a = square(3.0);

Page 17: Building Abstractions with Data  (Part 1)

How About This?double x = 3;int a = square(x);

Page 18: Building Abstractions with Data  (Part 1)

How About This?double x = 3;int a = square(x);

It’s kind of annoying that our square procedure can’t work for real numbers too. We’ll fix this later so that we can have a generic procedure definition that works for both integers and real numbers.

Page 19: Building Abstractions with Data  (Part 1)

A Quick Fix?static double square(double x){

return x*x;}…double x = 3;double y = square(x); // this works nowdouble a = square(3.5); // and so does thisint b = square(5); // but now this won’t work

Page 20: Building Abstractions with Data  (Part 1)

A Quick Fix?static double square(double x){

return x*x;}…double x = 3;double y = square(x); // this works nowdouble a = square(3.5); // and so does thisint b = square(5); // but now this won’t work

The complete fix? Much later, or maybe in CS21B.

Page 21: Building Abstractions with Data  (Part 1)

How About This?boolean a = square(3);

Page 22: Building Abstractions with Data  (Part 1)

How About This?boolean a = square(3) > square(4);

Page 23: Building Abstractions with Data  (Part 1)

How About This?boolean a = square(3) + square(4);

Page 24: Building Abstractions with Data  (Part 1)

How About This?static int square(int x){

return "Hello";}

Page 25: Building Abstractions with Data  (Part 1)

The void Return Type►Recall: imperative programming

insists that some instructions are statements, and others are expressions.►Expressions always have values.►Statements do not always do.

Page 26: Building Abstractions with Data  (Part 1)

The void Return Type►Some instructions can be statements

without values.► The print statement doesn’t have an

output value, because it already directly prints out to console. There’s no point keeping its “value” somewhere or using it in another expression.

► Same goes with main.

Page 27: Building Abstractions with Data  (Part 1)

The void Return Type►So, we invent a new “return type”

called void.►Putting void as a return type for a

procedure definition means that the procedure does something, but does not return a value to the procedure that called it.

Page 28: Building Abstractions with Data  (Part 1)

Examplestatic void sayFavorite(String name, int number)

{

print(person);

print("'s favorite number is ");

print(number);}

sayFavorite("Grandma", 42);

int x = sayFavorite("Grandma", 42);

Page 29: Building Abstractions with Data  (Part 1)

Examplestatic void sayFavorite(String name, int number)

{

print(person);

print("'s favorite number is ");

print(number);}

sayFavorite("Grandma", 42);

int x = sayFavorite("Grandma", 42);

Ok. Procedure call is a statement. Prints “Grandma’s favorite number is 42”.

Page 30: Building Abstractions with Data  (Part 1)

Examplestatic void sayFavorite(String name, int number)

{

print(person);

print("'s favorite number is ");

print(number);}

sayFavorite("Grandma", 42);

int x = sayFavorite("Grandma", 42);Not ok. Procedure call does not produce a value. Alternatively, procedure does not have the correct return type.

Page 31: Building Abstractions with Data  (Part 1)

Examplestatic void sayFavorite(String name, int number)

{

print(person);

print("'s favorite number is ");

print(number);}

sayFavorite("Grandma", 42);

int x = sayFavorite("Grandma", 42);

By the way, the String is another built-in type over the set of words or series of characters.

Page 32: Building Abstractions with Data  (Part 1)

Examplestatic void sayFavorite(String name, int number)

{

print(person);

print("'s favorite number is ");

print(number);}

sayFavorite("Grandma", 42);

int x = sayFavorite("Grandma", 42);

Strings can take on series of characters enclosed in double quotes as values.

Page 33: Building Abstractions with Data  (Part 1)

Question►Why is it possible to

print(square(4));►But not to

print(print(4));?

Page 34: Building Abstractions with Data  (Part 1)

Question►Why is it possible to

print(square(4));►But not to

print(print(4));? All expressions have

values, but not all procedure calls do.

The print procedure has a void return type specifier.

Page 35: Building Abstractions with Data  (Part 1)

Outline►The Notion of Types►Abstractions with Data Types►Same Type, Different Implementations

Page 36: Building Abstractions with Data  (Part 1)

Three Basic Kinds of Answers to Computational Questions

►Number►How far is the earth from the sun?

►Yes/No► Is Venus farther from the earth from the

sun?►Words►What are the planets closer to the sun

than the earth is?

Page 37: Building Abstractions with Data  (Part 1)

Review: “Problem” Versions for Those Questions

►Number►How far is a given planet from the sun?

►Yes/No► Is this given planet farther from that

given planet from the sun?►Words►What are the planets closer to the sun

than this given planet is?

Page 38: Building Abstractions with Data  (Part 1)

Three Basic Kinds of Input to Computational Problems

►Number► Given mass and acceleration, what’s the

force?►Yes/No

► Depending on whether the stock goes up or down, what’s the best next investment move?

►Words► Given a search phrase, what are the most

relevant web pages?

Page 39: Building Abstractions with Data  (Part 1)

Three Kinds of Primitive Data Types

►Numerical Data Types►Central assumption of information

theory: everything can be represented as a number

►Numbers encoded in binary (0s and 1s)

►Usually in many variants for efficiency’s sake

►The Boolean Data Type►True or False►Assign 0 to false, 1 to true

Page 40: Building Abstractions with Data  (Part 1)

Three Kinds of Primitive Data Types

►Symbolic Data Types► Characters

►Can be represented as numbers, and later encoded to 0s and 1s

► Strings (not really primitive, because Strings are sequences of characters)

► Maybe more advanced A.I. can answer some “how” and “why” questions, but even for those, symbolic data will be enough.

Page 41: Building Abstractions with Data  (Part 1)

Primitive Data Types in Java►Read about them here:

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

Page 42: Building Abstractions with Data  (Part 1)

Are These Enough?►Consider:►Given the x and y coordinates of a

point, find the x and y coordinates of its reflection across the line with the given A, B, and C coefficients in its equation in general form.

►Overly detailed!►And what if we want to expand to three

dimensions later?

Page 43: Building Abstractions with Data  (Part 1)

Are These Enough?►Limitation of Java:►Can’t have more than one output value

►Only one return statement per procedure►Only one return value per return

statement►Can’t output both x and y as two

numbers from the same procedure, even if it makes sense to let one procedure simultaneously produce them

Page 44: Building Abstractions with Data  (Part 1)

Are These Enough?►Other kinds of input:►Sound input►Keyboard/controller input►Biometric sensors

Page 45: Building Abstractions with Data  (Part 1)

Are These Enough?►Information comes in many physical

kinds.►Light, sound, matter, etc.

►Information comes in many conceptual kinds.►Money, personal records, shapes, etc.

Page 46: Building Abstractions with Data  (Part 1)

Are These Enough?►Every kind of data can be broken

down into numbers (even symbolic and Boolean data).

►For complex systems though, we don’t want to go to the level of primitives all the time.

Page 47: Building Abstractions with Data  (Part 1)

Data Abstraction► It’s better to say:

► Given a point, find its reflection across a given line.► Point and line are compound data types.

► Procedure for doing this doesn’t have to worry about how points or lines are represented in terms of primitives, as long as the representation obeys certain properties.► Important point (no pun intended) we’ll get to later.

Page 48: Building Abstractions with Data  (Part 1)

Adding Fractions: Without Data Abstraction

static int numerator-add(int a, int b, int c, int d) {

return a * d + b * c;

}

static int denominator-add(int a, int b, int c, int d) {

return b * d;

}

Page 49: Building Abstractions with Data  (Part 1)

Adding Fractions: With Data Abstraction

static Fraction add(Fraction a, Fraction b) {int num = num(a) * denom(b) +

num(b) * denom(a);int denom = denom(a) * denom(b);return makeFraction(num, denom);

}

Page 50: Building Abstractions with Data  (Part 1)

Interfacing with Primitives► Input to outer procedure (world) might

still be given as primitive data.► To chunk the primitive data, we need to use

constructors.►Output from outer procedure (world)

might still need to be primitive data.► To examine (and print out) the parts of a

chunked piece of data, we need to use selectors.

Page 51: Building Abstractions with Data  (Part 1)

Interfacing with Primitives►Programs that use Fractions can be

shielded from how the constructors and selectors are implemented.

Page 52: Building Abstractions with Data  (Part 1)

Adding Fractions: With Data Abstraction

static Fraction add(Fraction a, Fraction b) {int num = num(a) * denom(b) +

num(b) * denom(a);int denom = denom(a) * denom(b);return makeFraction(num, denom);

}

calls to selectors

Page 53: Building Abstractions with Data  (Part 1)

Adding Fractions: With Data Abstraction

static Fraction add(Fraction a, Fraction b) {int num = num(a) * denom(b) +

num(b) * denom(a);int denom = denom(a) * denom(b);return makeFraction(num, denom);

}

call to constructor

Page 54: Building Abstractions with Data  (Part 1)

Adding Fractions: With Data Abstraction

static Fraction add(Fraction a, Fraction b) {int num = num(a) * denom(b) +

num(b) * denom(a);int denom = denom(a) * denom(b);return makeFraction(num, denom);

} We now have an add procedure for fractions that doesn’t care about how the fractions are represented as primitives – new barrier of abstraction.We’re operating on a fraction as a whole concept, without worrying about how its parts are built.

Page 55: Building Abstractions with Data  (Part 1)

Using the Data Abstractionpublic static void main(String args[]){

Fraction x = makeFraction(3, 2);Fraction y = makeFraction(1, 5);Fraction sum = add(x, y);

}

Page 56: Building Abstractions with Data  (Part 1)

Using the Data Abstraction with Input/Output

public static void main(String args[]){

int a = 3, b = 2, c = 1, d = 5;Fraction x = makeFraction(a, b);Fraction y = makeFraction(c, d);Fraction sum = add(x, y);println(num(sum));println(denom(sum));

}

Page 57: Building Abstractions with Data  (Part 1)

But How Do We Implement the Following Procedures?

static Fraction makeFraction(int num, int denom) {

// ?

}

static int num(Fraction x) {

// ?

}

static int denom(Fraction x) {

// ?

}

selectors

How does the lower-level data type designer implement these so that the higher-level procedure designer can use a fraction as a single concept?

constructor

Page 58: Building Abstractions with Data  (Part 1)

Implementing the Data Typestatic class Fraction{

int numerator;int denominator;

}A fraction is made out of two integers.

fields

Page 59: Building Abstractions with Data  (Part 1)

Implementing the Constructors and Selectors

static Fraction makeFraction(int num, int denom) {

Fraction f = new Fraction();

f.numerator = num;

f.denominator = denom;

return f;

}

static int num(Fraction x) {

return x.numerator;

}

static int denom(Fraction x) {

return x.denominator;

}

Page 60: Building Abstractions with Data  (Part 1)

Implementing the Constructors and Selectors

static Fraction makeFraction(int num, int denom) {

Fraction f = new Fraction();

f.numerator = num;

f.denominator = denom;

return f;

}

static int num(Fraction x) {

return x.numerator;

}

static int denom(Fraction x) {

return x.denominator;

}

Call to primitive (built-in) constructor:Request for a chunk of memory to store the parts of my data

Page 61: Building Abstractions with Data  (Part 1)

Implementing the Constructors and Selectors

static Fraction makeFraction(int num, int denom) {

Fraction f = new Fraction();

f.numerator = num;

f.denominator = denom;

return f;

}

static int num(Fraction x) {

return x.numerator;

}

static int denom(Fraction x) {

return x.denominator;

}

Dot operator: call to primitive selectors.

f.numerator is…In English: f’s numerator variable/fieldIn French: numerator du/de là f

The field belongs to the data, not the data type!Each new Fraction has its own numerator and denominator fields.

Page 62: Building Abstractions with Data  (Part 1)

Practice Programming Problem: Fractions

►Include the implementation for the Fraction data type, constructor, and selectors above in your program.

►Include the add procedure above.►Create procedures for subtracting,

multiplying, dividing, and printing Fractions.

Page 63: Building Abstractions with Data  (Part 1)

Outline►The Notion of Types►Abstractions with Data Types►Same Type, Different

Implementations

Page 64: Building Abstractions with Data  (Part 1)

Why Not Directly Use The Primitives?

static Fraction add(Fraction a, Fraction b) {Fraction f = new Fraction();f.numerator =

a.numerator * b.denominator + b.numerator * a.denominator;

f.denominator = a.denominator * b.denominator;

return f;}

Page 65: Building Abstractions with Data  (Part 1)

Why Not Directly Use The Primitives

►Because the non-primitive constructors and selectors might need to be made non-trivial

►Same reason for not directly using primitive operators only

Page 66: Building Abstractions with Data  (Part 1)

Implementing Fractions in Lowest Terms

►Two possibilities:►Let the selectors do the reduction►Let the constructor do the reduction

►Another way: use primitive constructors and selectors, and do the reduction in add.

►But now, you have to do it for all the other operations too!

►Messy: mixing data type use and implementation

Page 67: Building Abstractions with Data  (Part 1)

Selectors Do the Reductionstatic int num(Fraction x) {

int divisor = gcd(x.numerator, x.denominator);

return x.numerator / divisor;}static int denom(Fraction x) {

int divisor = gcd(x.numerator, x.denominator);

return x.denominator / divisor;}

Page 68: Building Abstractions with Data  (Part 1)

Constructor Does the Reduction

static Fraction makeFraction(int num, int denom) {

Fraction f = new Fraction();

int divisor = gcd(num, denom);

f.numerator = num / divisor;

f.denominator = denom / divisor;

return f;

}

Page 69: Building Abstractions with Data  (Part 1)

Which Is Better?►Depends on application►Need to access Fractions many times?

Let Fractions be stored in lowest terms (constructor does the reduction).

►Need to create many Fractions? Reduce to lowest terms only when accessing (selectors do the reduction).

Page 70: Building Abstractions with Data  (Part 1)

Which Is Better?►The procedures that operate on Fractions don’t have to change depending on this decision.

►Yet another way: reduce only when printing►May cause issues when Fractions get

large

Page 71: Building Abstractions with Data  (Part 1)

Layers of Abstraction for Data

Programs That Use FractionsOperations on Fractions

Constructors for Fractions

Primitive Constructor

Ways to Implement Primitive Constructors

Selectors for Fractions

Primitive Selector

Ways to Implement Primitive Selectors

Page 72: Building Abstractions with Data  (Part 1)

Practice Programming Problem: Fractions in Lowest

Terms►Implement Euclid’s gcd algorithm (you

may grab a copy from the internet and don’t care that you don’t understand how it works) so that Fractions are printed out in lowest terms.

►Try out the two different ways of implementing the Fraction (in lowest terms) data type. Historical side note:

Euclid’s algorithm is one of the first non-trivial algorithms.

Page 73: Building Abstractions with Data  (Part 1)

The Fields Can Change Too►Example:►Point given in x-y rectangular

coordinates►Point given in r-theta polar coordinates►Both must have a constructor that

takes and another that takes (there can be multiple constructors for one type).

►Both must have selectors for all four: , , ,

Page 74: Building Abstractions with Data  (Part 1)

Practice Programming Problem: Points

►Create two different implementations for a 2D Point data type: a rectangular and a polar.

►Make sure each has two constructors►One takes and ►Another takes and

►Make sure each has four selectors► getX, getY, getR, getTheta

Page 75: Building Abstractions with Data  (Part 1)

Summary►A programming language can have a

type system to enhance meaningfulness and safety.

►Just as with procedures, we use abstraction with data to manage complexity.

►Compound data types can be built out of primitive data types.

Page 76: Building Abstractions with Data  (Part 1)

Summary►The data type definition is shielded

from its use with constructors and selectors.

►There are different ways to implement a data type.

Page 77: Building Abstractions with Data  (Part 1)

Next Time…►More combinations with data types►Comparison with procedural

abstraction►Moving from procedural to OOP