Abstract Data Types II

Download Report

Transcript Abstract Data Types II

Abstract Data Types II
Sufficient operations

Operations on an ADT are sufficient if they meet all the
requirements

They must be able to create all the values and perform all the
operations required by the application


Remember that the application cannot directly access the internal
values
They should be able to create all the values and perform all
the operations required by any application in a given class of
applications
2
Necessary operations

An operation on an ADT is necessary if omitting it
would fail to meet the requirements


If the application can implement an operation easily and
efficiently by combining other operations, that operation is
unnecessary
It’s OK to have unnecessary operations if they add
significantly to the convenience of using the ADT
3
Convenience operations


An operation is a convenience operation if it could be
accomplished by some overly complex combination of
other operations
People like things simple


A class with 50 or more methods is just overwhelming
Convenience operations should be justified




Will it be used often?
Does it really simplify the user’s task?
Would the user expect this operation to be provided?
Is it significantly more efficient?
4
Necessary and sufficient operations

A class should define a necessary and sufficient
set of operations


Convenience operations should be justified
Similarly, a class should have a necessary and
sufficient data representation


A class should not contain data that can be easily
computed from other data in the class
This is another application of the DRY principle
5
Example: Strings

Necessary and sufficient operators:


A constructor: public String(char[] chs)
Ways to access data:





public int length()
public charAt(int index)
Would you be happy with just these?
If you invented the String class, could you justify
operations such as equals and string concatenation?
Convenience operators aren’t all bad!
6
Types of operations



A constructor creates a value of the ADT from input
values
An accessor uses a value of the ADT to compute a value
of some other type
A transformer uses a value of the ADT to compute
another value of the ADT


A mutative transformer changes the value of the ADT it is
given
An applicative transformer takes one ADT and, without
changing it, returns a new ADT
7
Requirements

The constructors and transformers must together be
able to create all legal values of the ADT



Or, at least, any needed by the application
For a general use ADT, this means all legal values
The accessors must be able to extract any data

Or, at least, any needed by the application
8
Operations in Java

Constructors can be implemented with Java
constructors

A constructor’s job is to construct an object of a class in
a valid state
That should be a constructor’s only job
Accessors and transformers can be implemented
with Java methods




Mutative transformers are typically (but not always)
implemented as void methods
Sometimes they both modify an object and return it
9
Factory methods

The problem with a constructor is that it will always construct an
object of a given type

This isn’t always what you want





You may want to check the constructor’s parameters for validity
You may want to return an existing object, if there is one
 For example, you really only need one EOL Token
You may want to return objects of different types
You can solve these problems by using a factory method
Example:

public Animal create(String voice) {
if (voice.equals("woof")) return new Dog();
if (voice.equals("meow")) return new Cat();
if (voice.equals("moo")) return new Cow();
throw new IllegalArgumentException(voice);
}
10
Another factory method

class Token {
Type t;
Object v;
Token eolToken = new Token(Type.EOL, "\n");
private Token(Type t, Object v) { // constructor
this.t = t;
this.v = v;
}
}
public Token create(Type t, Value v) {
if (t == Type.EOL) return eolToken;
else return new Token(t, v);
}
11
Example ADT: String

Constructors:



Accessors:



public int length()
public char charAt()
Transformers (applicative only):



"This is syntactic sugar for a constructor"
public String(char[] chs)
public String substring(int i, int j)
public String concat(String that) (also +)
Etc.
12
Immutable objects


A String is immutable: it cannot be changed
The String class has no mutative transformers


Advantages:



Operations such as string concatenation create new Strings
Efficient (for most uses)
Easy to use and simple to understand (changing a String in
one object doesn’t change it in other objects)
Disadvantage:

Every call to a transformer creates a new String
13
Example: StringBuilder

Constructors:


Accessors:



none
Transformers (mutative):


public int length()
public char charAt()
Transformers (applicative):


public StringBuilder(String s)
public StringBuilder append(Object obj)
Etc.
14
Mutable objects



A StringBuilder is mutable: it can be changed
The StringBuilder class has both applicative and
mutative transformers
Advantage:


Disadvantage:


Efficient (for doing a lot of string manipulation)
Can be confusing (example coming up shortly)
Operations on Strings are done by converting to
StringBuffers (like StringBuilders), doing the work,
and converting back
15
Safe use of Strings
public class Person {
private String name;
Person(String name) {
this.name = name;
}
}
String jan = "Jan";
Person doctor = new Person(jan);
String dan = "D" + jan.substring(1, 2);
Person secretary = new Person(dan);
16
Unsafe use of StringBuilders
public class Person {
private StringBuilder name;
Person(StringBuilder name) {
this.name = name;
}
}
StringBuilder buffer = new StringBuilder("Jan");
Person doctor = new Person(buffer);
buffer.setCharAt(0, 'D');
Person secretary = new Person(buffer);
17
Summary



A class should define a necessary and sufficient set of
operations
Convenience operations should be justified
Operations can be classified as:




Constructors
Accessors
Transformers (applicative or mutative)
Immutable objects are often preferable to mutable
objects
18
The End
Eclipse Hints
● If you lose track of tabs or entire
panes in Eclipse, choose Window 
Reset Perspective
19