Upload
collin-hardy
View
214
Download
1
Embed Size (px)
Citation preview
Abstract data types
What does ‘abstract’ mean? From Latin: to ‘pull out’—the essentials
– To defer or hide the details– Abstraction emphasizes essentials and defers the
details, making engineering artifacts easier to use
I don’t need a mechanic’s understanding of what’s under a car’s hood in order to drive it– What’s the car’s interface?– What’s the implementation?
Floating point numbers
You don't need to know how much about floating point arithmetic works to use float– Indeed, the details can vary depending on
processor, even virtual coprocessor– But the compiler hides all the details from you--some
numeric ADTs are built-in– All you need to know is the syntax and meaning of
operators, +, -, *, /, etc. Hiding the details of implementation is called
encapsulation (data hiding) See multimedia: ADT for digits (properties)
ADT = properties + operations
An ADT describes a set of objects sharing the same properties and behaviors – The properties of an ADT are its data
(representing the internal state of each object• double d; -- bits representing exponent & mantissa
are its data or state
– The behaviors of an ADT are its operations or functions (operations on each instance)• sqrt(d) / 2; //operators & functions are its behaviors
Thus, an ADT couples its data and operations– OOP emphasizes data abstraction
Formal, language-independent ADTs An ADT is a formal description, not
code; independent of any programming language– Why is code independence a good idea?
Promotes design by contract:– Specify responsibilities of suppliers and
clients explicitly, so they can be enforced, if necessary
Generic Queue ADT An ADT specification has six parts
– The first three dealing with syntax… NAME, SETS and SIGNATURES
NAME Queue<I> SETS
I set of all items (generic type)Q set of all QueuesB set of Boolean (elements T and F)N set of natural numbers, including 0
The NAME specifies the name of a type– Generic parameter, <I>, to specify elements of collection types
SETS specifies all the types of parameters in SIGNATURES section
SIGNATURES section (see umprobso—“you are adding”)
SIGNATURES
Queue() -> Q front(Q) -/-> I
isEmpty(Q) -> B enqueue(Q, I) -> Qlength(Q) -> N dequeue(Q) -/-> Q
SIGNATURES specifies the operations or services provided by ADT Notation of mathematical functions, with one or more inputs and producing one
result:– isEmpty(Q) -> B: Given a Queue (domain), produces a Boolean (range)
Functions have no side effects at all:– front(Q): given a Q, returns an item (no change)– enqueue(Q, I): returns a NEW Queue– dequeue(Q): returns another Queue
Functional approach may seem inefficient, but facilitates semantics– Implementation should preserve the abstract behavior of ADT
Syntax is relatively easy to specify; semantics is a bit harder….
Full vs. partial functionsSIGNATURES
Queue() -> Q front(Q) -/-> I
isEmpty(Q) -> B enqueue(Q, I) -> Q
length(Q) -> N dequeue(Q) -/-> Q -> denotes a full function over the set Q, always producing the
specified type of output ‑/‑> denotes a partial function over the set Q, which may not
always produce the output– Instead its result may be undefined
When is front undefined? When is enQueue undefined? Answering these questions about partial functions is semantics Specifically, the preconditions
– A partial function is undefined if any of its preconditions do not hold
Semantics of ADTs
Three sections for semantics of ADTs: variables, preconditions, and postconditionsVARIABLES
i:I; q, r:Q; n:N; b:BPRECONDITIONS
front(q) -> isEmpty (q) = falsedequeue(q) -> isEmpty (q) = false
VARIABLES -- declares instances of SETS, needed in PRE- and POST-CONDITIONS
How are the variables used in PRECONDITIONS? What is the scope of these variables?
Preconditions Specify constraints on any partial functions, indicating when they fail front(q) -> isEmpty (q) = false //What does this constraint tell you?
– PRECONDITIONs very explicit about the when a partial function fails Formalizes design by contract: analogous to written business contracts
– Inspire confidence between clients and suppliers of products E.g., a contract for building a house, or a contract to write a book
– A contract specifies the product that the supplier will produce– A contract also specifies the price the client will pay and other terms– Such as constraints on a contract—installments, liability, etc.
ADT specifies a contract between the supplier and client of an ADT– Supplier warrants that ADT will produce the specified behavior– so long as client provides the expected inputs– so long as client doesn’t violate the pre-conditions, behaviors will work– if the client violates the contract (any pre-condition), the behavior fails– Yet even the failure is predictable and can be handled predictably
Thus PRECONDITIONS also set up exception handling Note: no need to include trivial preconditions, e.g., isEmpty(q) -> true.
Postconditions
Define effects of functions, i.e., what they accomplishPOSTCONDITIONS
Queue() = (qList = List()) isEmpty(q) = null(qList)length(q) = length(qList)front(q) = head(qList)enqueue(q,i) = (qList = append(qList, i))dequeue(q,i) = (qList = tail(qList, i))
First postcondition defines constructor in terms of List– Reusing List implies a constructive semantics, building
from other ADTs, already defined Why is constructive semantics a good fit for
OOP? What does second postcondition tell you?
Axiomatic semantics
Defines relations between operations strictly in terms of universal axioms (self-evident truths)– Axioms define an ADT independently of other ADTs– Constructive approach builds new ADTs based on
knowledge of existing ones– The buck has to stop somewhere: e.g., the List ADT
uses an axiomatic semantics– Book has an optional section on universal axioms
List postconditions (axioms)
null(List()) = true //How self-evident? null(prepend(list1,i)) = null(append(list1,i)) =
false //Explain? length(List()) = 0 length(append(list1, i)) = length(list1)+1 tail(append(list1,i)) = if null(list1) then []
else append(tail(list1),i))
Constructive semantics(See umprobso, “Queue of football”)
Explain rest of Queue’s postconditions:
front(q) = head(qList)
enqueue(q,i) = (qList = append(qList, i))
dequeue(q,i) = (qList = tail(qList, i)) Why would this be harder with axioms?
– (See umprobso, “axiomatic”)
Inheritance and ADTs
See Employee example How does inheritance affect name section?
– NAME Employee SUPERTYPES Person How does inheritance affect other sections?
– Employee inherits functions for name, address, etc, from Person– Inherits both syntax (SIGNATURES) and semantics – No need to redefine functions in Employee unless they do
something different• So Employee just supplies new constructor, GROSS_PAY, TAX_DUE
– Semantics can benefit further from reuse implied by inheritance– Constructor for Employee invokes constructor for Person
Could add notation {abstract} to specify abstract functions
Fruit ADT assignment
Your assignment (on Blackboard):– Improve your UML analysis
• Per my comments• You may want to improve my analysis!
– Develop an ADT design• Think of it as a contract that you could hand
over to a programmer (that would be you!)
– Extra credit: design a user interface ADT(s)• loosely coupled to problem domain ADT