Download Solution - NUS School of Computing

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
CS1020: Data Structures and Algorithms I
Tutorial 3 – Abstract Data Types
10th September 2013
1. [Encapsulation] Find out what is wrong with the code below in terms of encapsulation
principle.
class Point {
private int x,y;
public Point(int _x, int _y) { x = _x; y = _y; }
public int getX() { return x; }
public int getY() { return y; }
public void setX(int _x) { x = _x; }
public void setY(int _y) { y = _y; }
}
class Rectangle {
private Point topL, botR; // top-left & bottom-right
public Rectangle(int x1, int y1, int x2, int y2) {
// Assume correct input
topL = new Point(x1, y1);
botR = new Point(x2, y2);
}
// Pre-Condition: Point is initialized correctly
// Post-Condition: Moved up (Y-axis) by the given distance
public void moveUp(int distance) {
topL.setY(topL.getY() + distance);
botR.setY(botR.getY() + distance);
}
// Move down, left, and right is omitted for brevity
}
public Point getTopLeft() { return topL; }
public Point getBottomRight() { return botR; }
Suggested solution: The public Point getTopLeft breaks encapsulation since now, we can change
the shape of the rectangle as we are given the Point class. So, to preserve encapsulation, either
return the point as separate integer, or return a new point (i.e. return new Point(topL.getX(),
topL.getY());
2
CS1020: Data Structures and Algorithms I
2. [ADT] Design an ADT that represents a module. The data of the ADT should include the
module name, the module code, the credit, time, lecturer, student enrolled. Each student has
information of name, matric number, faculty and contact information (contact information
may contain more than one). Each lecturer has information such as name, faculty, and contact
information.
a. Include operations for the change of time, the display the statistics of the module (eg.
the number of students), etc. (Note: No implementation is needed. But for the
functions, please indicate pre- and post-conditions).
b. Create a generic list (involveList<E>) for the module class to store the students and
lecturers information. Include operations of adding to front, adding to back, removing
to front, removing from back, and searching index. For simplicity you can use
ArrayList implementation of the List interface to you may use ArrayList for
implementation.
// module ADT
class Module {
// add codes here
}
class Student {
// add codes here
}
class Lecturer {
// add codes here
}
Suggested solution: See tut03Ex02.java
3. [Abstract classes vs. Interfaces] An abstract class is one that contains some abstract
methods, i.e. without implementation. Below is an example of a Complex Abstract class,
which you can extend as the ComplexCart and ComplexPolar classes. Learn abstract class by
yourself (http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html). Contrast the
abstract class below with the interface Complex found in your lecture notes.
3
CS1020: Data Structures and Algorithms I
public abstract class
public abstract
public abstract
public abstract
public abstract
AbstractComplex {
double realpart(); // returns this.real
double imagpart(); // returns this.imag
double angle(); // returns this.angle
double mag(); // returns this.mag
public abstract void add(AbstractComplex c); // this=this+c
public abstract void minus(AbstractComplex c); // this=this-c
public abstract void times(AbstractComplex c); // this=this*c
/**
Since toString is same for both Cartesian and Polar forms, we can
implement it here to avoid implementing it twice in the Cartesian and
Polar subclasses.
*/
public String toString() {
return stringForm();
}
}
/**
* We can even make private methods!
*/
private String stringForm() {
if (imagpart() == 0)
return (this.realpart() + "");
else if (imagpart() < 0)
return (realpart() + "" + imagpart() + "i");
else
return (realpart() + "+" + imagpart() + "i");
}
a. What are the differences between abstract classes and interfaces? (You can compare the
abstract class Complex above and the interface Complex in your lecture notes, but there
are more differences than what we have shown.)
Suggested Solution:
Abstract Class
Interface
Describes similar functionality and data for all
the classes that extend it
Describes similar functionality for all
classes that implements it
Can have implemented methods and attributes
Only has method signatures
(unimplemented); Methods can only be
public
Can have non-final data fields
All data attributes must be final
Classes can only extend a single abstract class
Classes can implement multiple interfaces
4
CS1020: Data Structures and Algorithms I
Abstract Class
Classes that extend an abstract class need not
provide implementation for all abstract
methods in their superclass. They will be in
turn abstract classes.
Interface
Classes that implement an interface must
provide implementation for all methods
defined in the interface.
b. When should we use an interface instead of an abstract class and vice versa?
Suggested solution: Abstract classes can contain implementations for some of the declared
methods, but interfaces cannot. If there are some methods with common implementations
across all (or most) subclasses of the base class, then these methods’ common
implementations could be put in the abstract class. Otherwise, use interfaces.
c. The Java library has specified a few interfaces that it uses to perform commonly used
tasks. Find out what the following interfaces are used for, and give an example of when
they are used:
i.
Comparable
ii. Serializable
iii. List (as in Interface java.util.List)
iv. Runnable
Suggested solution:
i) Interface Comparable: Comparable interface has an abstract method compareTo which
can be implemented to compare non-primitive data types. Commonly used to sort the
objects in some particular order. E.g. If we want to sort BankAccounts, we can implement
the compareTo in the interface Comparable in BankAccount class such as compare them
by account number, account owner name, or account balance, before we can ask Java to
sort the BankAccounts for us.
(ii) Interface Serializable: Implement a class such that it can be written to file as bytecode (File-IO). This is also known as Object Persistence. Java allows us to dynamically
create objects in the program, however, these objects exist only as long as the program is
running. In cases where we need to save these data and use them the next time the program
starts up, we need to save the data into a file before the program exits. Implementing the
Serializable interface allows the object to be written to file and loaded from file without the
hassle of having to read its individual attributes and writing them individually into the file.
5
CS1020: Data Structures and Algorithms I
(iii) Interface List: An ordered collection (also known as a sequence). The user of this
interface has precise control over where in the list each element is inserted. The user can
access elements by their integer index (position in the list), and search for elements in the
list. ArrayList, LinkedList, Vector are some implementations of the interface list.
ArrayList class is a resizable array implementation, LinkedList class is a linked list
implmentatoin, and Vector class implements a growable array of objects. You can also
implement a non-resizable array of data, but you need mechanisms in your code to throw
exceptions or indicate to the user that an action (insertion, deletion, etc) did not succeed.
Do not confuse the Interface List (java.util.List) and the Class List (java.awt.List). The List
Class is used to render lists as graphics in Java. It is not covered in CS1020.
(iv) Interface Runnable: Implement parallel execution in Java, also known as Threading.
Multithreading refers to two or more tasks executing concurrently within a single program.
A thread is an independent path of execution within a program. Many threads can run
concurrently within a program. A Java program can have many threads, and these threads
can run concurrently, either asynchronously or synchronously. There are two ways to create
thread in java: (1) Implement the Runnable interface (java.lang.Runnable). (2) By
Extending the Thread class (java.lang.Thread).
It will not be covered in CS1020, but is a major part of future modules.
4. [Abstraction, coupling, coherence, information hiding] The ContactList software has been
partially implemented for you in the following code. Complete the Contact ADT so that the
ContactList software can work. Also take note of all the “// TODO” in the ContactList class
provided below. You may use the adstract class learned above for multipe contact methods
with the contact.
a. The Contact ADT should store the name of the contact, and multiple contact methods
with the contact. It must provide public methods to add contact methods. Deleting a
contact method is not required. What assumptions would you make? (Hint: a person
can have different contact methods eg. phone number, email, MSN, Skype, etc.)
b. Implement the Comparable interface on the Contact ADT so that the ContactList
software can sort the contacts by name in alphabetical order. If implemented
correctly, the test program should show a list of names sorted in alphabetical order.
c.
Identify the parts of the ContactList program where the principles of Abstraction,
coupling, coherence, and information hiding are used.
6
CS1020: Data Structures and Algorithms I
import java.util.Arrays;
import java.util.Vector;
public class ContactList {
private Vector<Contact> contacts;
public static void main(String[] args) {
ContactList myContactList = new ContactList();
Contact contact = new Contact("Charlie");
// TODO add a few contact methods here
myContactList.addContact(contact);
contact = new Contact("Bob");
// TODO add a few contact methods here
myContactList.addContact(contact);
contact = new Contact("Abraham");
// TODO add a few contact methods here
myContactList.addContact(contact);
Contact[] sortedList = myContactList.sortContactsByName();
for (Contact c : sortedList) {
Contact class?
Object.
// TODO using this line means you need to implement what in
// Hint: You need to override a method inherited from
System.out.println(c);
}
}
public ContactList() {
contacts = new Vector<Contact>();
}
public void addContact(Contact c) {
contacts.add(c);
}
public Contact getContact(String name) {
for (Contact c : contacts) {
if (c.getName().equals(name)) return c;
}
return null; // no such person
}
public void deleteContact(String name) {
Contact c = getContact(name);
if (c != null)
contacts.remove(c);
}
public Contact[] sortContactsByName() {
Contact[] contactArray = contacts.toArray(new
Contact[contacts.size()]);
// TODO Contact class has to implement Comparable // interface
for this to work!
Arrays.sort(contactArray);
// Don't bother how it works now, sorting in Java // will be
covered later on.
return contactArray;
}
}
7
CS1020: Data Structures and Algorithms I
Suggested solution:
class Contact implements Comparable<Contact> {
String name;
Vector<ContactMode> comms;
public Contact(String name) {
this.name = name;
comms = new Vector<ContactMode>();
}
public String getName() {
return name;
}
public void addContactMode(ContactMode cm) {
comms.add(cm);
}
public void removeContactMode(int i) {
comms.remove(i);
}
// implement compareTo() of Comparable for sorting objects in Arrays class
@Override
public int compareTo(Contact other) {
return name.compareTo(other.getName());
}
}
// redefine toString()for printing contacts
@Override
public String toString() {
String str = "Name: " + name;
for (ContactMode c : comms)
str += "\n" + c.getDetails();
return str;
}
abstract class ContactMode {
protected final String type;
public ContactMode(String type) {
this.type = type;
}
public String getType() {
return type;
}
}
public abstract String getDetails();
8
CS1020: Data Structures and Algorithms I
class PhoneNumber extends ContactMode {
private int countryCode;
private String phone;
public PhoneNumber(int countryCode, String num) {
super("Phone");
this.countryCode = countryCode;
this.phone = num;
}
}
@Override
public String getDetails() {
return type + ": (+" + countryCode + ") " + phone;
}
class Email extends ContactMode {
private String email;
public Email(String email) {
super("Email");
this.email = email;
}
}
@Override
public String getDetails() {
return type + ": " + email;
}
//Also, replace the main function:
public static void main(String[] args) {
ContactList myContactList = new ContactList();
Contact contact = new Contact("Charlie");
contact.addContactMode(new PhoneNumber(65, "0012-3456"));
contact.addContactMode(new Email("[email protected]"));
myContactList.addContact(contact);
contact = new Contact("Bob");
contact.addContactMode(new Email("[email protected]"));
myContactList.addContact(contact);
contact = new Contact("Abraham");
contact.addContactMode(new Email("[email protected]"));
myContactList.addContact(contact);
Contact[] sortedList = myContactList.sortContactsByName();
}
for (Contact c : sortedList) {
// enhanced for loop
System.out.println(c);
// use toString() of contacts
}
9
CS1020: Data Structures and Algorithms I
Principles used in ContactList:
Abstraction: ContactList only needs to care about each Contact, and not the different
modes of communication. In this case, we know that we need to model different classes for
Email and PhoneNumber, but at the ContactList level, we abstract these details out and
model the problem with only Contacts.
Coupling: ContactList maintains only a list of Contacts. Contact only maintains a list of
ContactModes. No need for ContactList to know what kind of contact modes are available,
like Email, PhoneNumber, etc.
Coherence: Each class only has methods that pertain to its own functions, eg. Sorting the
list of Contacts should be done in the ContactList, not Contact. ContactList implements
add() such that it only adds Contact objects, and does not know or bother with adding
ContactMethods within a given Contact. Similarly, Contact class implements add() such
that it adds ContactMethods, because that is what it is aware of.
Note: Coupling is usually contrasted with cohesion. Cohesion is closely related the various
functions/methods of a class. Coupling is how closely this class is integrated with
implementations of other classes, that a change in any other class will result in change in
this class. A high cohesion and low coupling is always desired. Low coupling often
correlates with high cohesion, and vice versa. Low coupling is often a sign of a
wellstructured computer system and a good design, and when combined with high
cohesion, supports the general goals of high readability and maintainability.
Information hiding: The “type” of ContactMode is hidden in the implementation and
Contact ADT does not have to know what type it is, as long as it extends ContactMode.
Once the type is set, it should also not change. For this reason, we “hide” the information
by making it protected, and provide only a getter and not setter for the type.
We also “hide” information in the form of implementation details. The user is unaware that
we stored the list of Contacts using a vector. Since this implementation is hidden, we can
now change its internal representation to use arrays instead, and the methods provided by
the ADT does not change.
10