SC ADT
R10: abstraction data types¶
access control¶
Private(only in the same class), public, no modifiers(only in the same package), protected(only in the same parentage)
-
Scope: same class, same package, subclass of other package, different class of other package
-
区分: instance variable vs. class name
What abstraction means¶
- fancy words? Not that fancy.
- Abstraction/modularity/encapsulation/information hiding/separation of concerns
- User-defined types
- type is characterized by the operations you can perform on it.
- abstract away from the details of data structure, memory storage, implementation
classifying types and operations¶
-
Types: mutable / immutable
-
Operations:
- Creator, create new objects of the type. Input: values
- constructor
- implemented as a static method called a factory method
- Producers. Input: existing objects
- Observer
- Mutators, change objects
- Creator, create new objects of the type. Input: values
What and how: what is ADT and how to design¶
- Representation
- Implementation
representation independence¶
Testing¶
R11: abstraction function & rep invariants¶
invariants¶
good ADTs preserve its own invariants.
-
mutable objects
-
public and private in access control
-
Immutable wrappers around mutable data types, get exception at runtime not at compile time.
- avoid representation exposure
Rep invariants and abstract function¶
abstract type can be divided into abstract value space and representation value space.
- every abstract value is mapped to by some rep value.
- Some abstract values are mapped to by more than one rep value.
- Not all rep values are mapped.
- Abstract function
AF: R -> A
- Rep invariant
RI: R->boolean //subset of rep values on which AF is defined
Implementations of an ADT means not only choosing the two spaces, but alse deciding which rep values are legal, and how to interpret them as abstract values.
Beneficent mutation¶
-
beneficent mutation: 改变rep value, 不改变abstract value
The rep value has changed to another that still maps to the same abstract value.
Documenting the AF, RI, and safety from rep exposure¶
- Rep exposure safety argument
- What an ADT spec
- may talk about
- Things that are visible to the client: parameters, return values, exceptions thrown by its operations
- Abstract values
- should not talk about
- details of the representation
- AF and RI should hide within the body of the class
- may talk about
ADT invariants replace preconditions¶
-
Encapsulate preconditions in ADTs
-
How to establish invariants
if an invariant of an ADT is
1. established by creators and producers 2. preserved by mutators, observers, and producers; and 3. no representation exposure occurs
then the invariant is true of all instances of the ADT.
R12:defining ADTs¶
Objectives:implement interfaces, generic types, enumerations and global functions operating on opaque type of ADT, determine subtyping relationship
Interface¶
> interfaces:¶
-
advantage:
- Interface specifies the contract for the client.
- Support multiple different representations
-
Java’s interfaces: do not include info about the representations
所以不需要提供有关interface的额外信息,比如:instance variables, instance method bodies, constructors
> subtypes:¶
- 编译器能检查子类型有无实现其父类的所有类型,但不能检查是否符合其规范。我们需要保证子类型的规范至少要和其父类一样的强劲。
“B is a subtype of A” means “every B is an A.” In terms of specifications: “every B satisfies the specification for A.
-
Declare subtypes in java
- declare that a class B is a subtype of an interface A, use
implements
:
1
2
3class ArrayList<E> implements List<E> {
...
}- declare that an interface is a subtype of another interface, using
extends
:
1
2
3interface SortedSet<E> extends Set<E> {
...
} - declare that a class B is a subtype of an interface A, use
> Example:mystring¶
需要注意的地方:
-
Constructor: valueOf(). The difference between concrete class’s static method and interface’s constructor
-
Inheritance: @override
-
Private constructors are allowed
-
abstraction barrier between ADT and its concrete representations
-
How clients use ADT?
1
2MyString s = new FastMyString(true);
MyString s = MyString.valueOf(true); //better- implement the creator operation
valueOf
as a static factory method in the interfaceMyString
- implement the creator operation
-
1 | /** |
> Why interfaces?¶
- 使用界面能为编译器和人们增加可读性。
- 从最开始抽象出独立的实现,然后再修正具体细节。能够在不同方式实现间权衡性能。
- 有意未明确的方法规范,在之后更具体的实现
- multiple view of one class. A java class may implement multiple interfaces.
- 通过从简单的实现到更复杂/严格的实现,一步步构建可信的方法实现
subclassing¶
和界面实现的区别在于:subclass 可以继承superclass的method bodies, fields;包含spec 和rep,而interface只包含spec。
Problem: what inheriting the rep means?
-
answer: 一个安全的subclass需要遵循两个合同,和用户的以及和其subclass的,而这导致了rep独立性被破坏的问题。
- rep exposure between the superclass and all its subclasses
- rep dependence between superclass and subclasses
- superclass and subclass can inadvertently break each other’s rep invariants
Static type vs. dynamic type:
-
Dispatching to the method
Java’s dynamic dispatch: it uses the implementation appropriate to the dynamic type of the object, not the static type of the reference that points to the object.
1 | FastMyString fms = new FastMyString(true); // recall that this represents the 4-character string "true" |
Object is static type known at compile time, while FastMyString is the typpe unknown until runtime.
Generic types¶
generic type: a type whose specification is in terms of a placeholder type to be filled in later. -> generic programming
Implementations:
-
Generic interface, non-generic implementation
1
2public interface Set<E> {)
public class CharSet implements Set<Character> {} -
Generic interface, generic implementation
1
2public interface Set<E> {}
public class HashSet<E> implements Set<E> {}
enumerations¶
enumeration: a small and finite values which can be defined as named constants.
和c struct相像。
-
Java 中.equals 和 == 的额外细节:equals在运行时间检查是否在意义上相同,而==检查两个对象是否是同一个reference。这在一般的比较中是有差异的,而在enum中由于只有唯一的reference,equals和==反而没什么区别,同时==符合fail fast的特点因为我们检查的正是它们是否是相同的reference指向唯一的enum中的值。
-
java中有内置的enum类型,自动提供一些操作:
ordinal()
is the index of the value in the enumeration, soJANUARY.ordinal()
returns 0.compareTo()
compares two values based on their ordinal numbers.name()
returns the name of the value’s constant as a string, e.g.JANUARY.name()
returns"JANUARY"
.toString()
has the same behavior asname()
-
可以自定义需要的enum
- An
enum
declaration can contain all the usual fields and methods that aclass
can. (Rep, methods, constants) - Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74public enum Month {
// the values of the enumeration, written as calls to the private constructor below
JANUARY(31),
FEBRUARY(28),
MARCH(31),
APRIL(30),
MAY(31),
JUNE(30),
JULY(31),
AUGUST(31),
SEPTEMBER(30),
OCTOBER(31),
NOVEMBER(30),
DECEMBER(31);
// rep
private final int daysInMonth;
// enums also have an automatic, invisible rep field:
// private final int ordinal;
// which takes on values 0, 1, ... for each value in the enumeration.
// rep invariant:
// daysInMonth is the number of days in this month in a non-leap year
// abstraction function:
// AF(ordinal,daysInMonth) = the (ordinal+1)th month of the Gregorian calendar
// safety from rep exposure:
// all fields are private, final, and have immutable types
// Make a Month value. Not visible to clients, only used to initialize the
// constants above.
private Month(int daysInMonth) {
this.daysInMonth = daysInMonth;
}
/**
* @param isLeapYear true iff the year under consideration is a leap year
* @return number of days in this month in a normal year (if !isLeapYear)
* or leap year (if isLeapYear)
*/
public int getDaysInMonth(boolean isLeapYear) {
if (this == FEBRUARY && isLeapYear) {
return daysInMonth+1;
} else {
return daysInMonth;
}
}
/**
* @return first month of the semester after this month
*/
public Month startOfNextSemester() {
switch (this) {
case JANUARY:
return FEBRUARY;
case FEBRUARY: // cases with no break or return
case MARCH: // fall through to the next case
case APRIL:
case MAY:
return JUNE;
case JUNE:
case JULY:
case AUGUST:
return SEPTEMBER;
case SEPTEMBER:
case OCTOBER:
case NOVEMBER:
case DECEMBER:
return JANUARY;
default:
throw new RuntimeException("can't get here");
}
}
} - An
ADTs in non-OOP languages¶
define ADT in non-oop languages like C: a group of globally-accessible functions that operate on an opaque data type.
(data abstraction)
1 | FILE* f = fopen("out.txt", "w"); // open a file for writing |
The notion of an abstract data type does not depend on language features like classes, or interfaces, or
public
/private
access control. Data abstraction is a powerful design pattern that is ubiquitous in software engineering.