Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
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