410 likes | 589 Views
George Blank University Lecturer. CS 602 Java and the Web. Object Oriented Software Development Using Java Chapter 6. Public and Helper Classes. A class intended for general use should be a public class. It must be declared public and reside in a file is the same as the class name.
E N D
George Blank University Lecturer
CS 602Java and the Web Object Oriented Software Development Using Java Chapter 6
Public and Helper Classes • A class intended for general use should be a public class. It must be declared public and reside in a file is the same as the class name. • A subordinate class used only by public classes is a helper class. It should not be declared public and, if it supports a single public class, should appear in the same file as the public class.
Nested or not? • If a helper class appears separately in a file with a public class, it is accessible only to that public class. See the example on the next slide. • If a helper class is nested inside a public class, it is accessible through that public class by subclasses of that public class unless they are combined in the same package. See the example on the slide following the next slide.
Example LinkedList.Java public class LinkedList implements List { protected Node head, tail; protected int count; //.. //implementation of Linked List } class Node { Object element; Node next, prev; }
Nested in LinkedList.Java public class LinkedList implements List { protected Node head, tail; protected int count; static protected class Node { Object element; Node next, prev; } //.. //implementation of Linked List }
Separate interface from implementation • It is good programming practice to use interfaces widely in Java. Whenever the functionality of a class can be implemented in different ways, create an interface that is polymorphic and broadly designed, then create different classes that extend the functionality to different cases. This requires a design practice of thinking about the most general case of a class before implementing the specific cases.
TFCL • The use of general interfaces is an example of the best practice of TFCL: Think first, code later. • In general, you want to spend time thinking about the problem you are solving before you start work on the solution. Clearly separate the problem domain from the solution domain.
Problems and Solutions • Concentrating on understanding the problem before you even consider a solution is an example of deferring decision making. In general, the earlier you make a decision the more likely you are to make a wrong decision. Every time you start to write code, you select one approach to a solution that precludes other approaches. If you decide before fully understanding the problem, you are less likely to choose the best, or even a good approach.
Related Java functions • The previous example, from the author of the text, may be confusing, as the Java class library provides an interface List and a Linked List in the Collections framework, which we will see in chapter 8. • Here he is just showing an example of a similar class. Do not confuse it with the class library interfaces and classes.
Declaring an interface • Also notice at this point how an interface is implemented. Instead of declaring a class, we declare an interface. Also, in an interface, there can be no implementation details. The member functions of the interface class are shown as prototypes, showing their type, name and arguments. Except in special cases, an interface and it’s members are usually declared public to facilitate creating classes to implement them.
Implementing the interface • Once you have declared an interface, implementing it is simple. All you have to do is declare a class that implements the interface. The implementing class then must provide an implementation for each of the methods declared in the interface. public class LinkedList implements list { public int size {…implementation of size…} …implementation of remaining class members…
Class Members • While the order of class members is semantically insignificant to the Java compiler, it still matters to human readers to make the class easy to understand. • A best practice is to order the members according to their accessibility and roles: • Public constructors • Public accessor or selectors (do not modify state) • Public mutators or modifiers (change state of objects) • Nonpublic constructors and auxiliary methods
Good organization for aPublic Class public class Aclass { <public constants> <public constructors> <public accessors> <public mutators> <nonpublic fields> <nonpublic auxiliary methods or nested classes> }
Avoid public fields • The object oriented principle of encapsulation suggests that attributes of a class should not be directly accessible. Instead, the fields should be accessed indirectly through methods of the class. • An accessor, get method, or getter is a method used to obtain the value of a field. • A mutator, set method, or setter is a method used to change the value of a field.
Accessors and Mutators • Requiring access to attributes only through accessors and mutators allow those methods to enforce constraints and security methods to avoid improper use of the fields and inconsistent data. • Preventing direct access to the data also protects against problems such as inconsistency related to simultanous use by different objects. Ths is a key virtue of encapsulation. The discussion of PolarPoint on pages 211-213 of the text explains the importance of this and is discussed on the next slide.
Example of get and set • Section 6.3 gives a clear example of information hiding and the reason for using accessors and mutators. • The class PolarPoint must be constrained to points that are the length of the radius away from the origin. To prevent invalid values for points, only a member method can set points using a mutator. There is no direct access to the values. While this is required for the example, it is good practice to use accessors and mutators broadly, not just when there is a clear need.
Complete Public Interface • The set of public methods defined in a class should provide full and convenient access to all of the functionality of the class.
Separate Interface from Implementation • If the functionality of a class can be implemented in different ways, it is advisable to separate the interface from the implementation. • This implements the Object Oriented principle of information hiding, so that changes in implementation will not affect clients of the class.
Java interfaces and C++ Headers • Java interfaces are similar to C++ header files, but there are key differences that make Java closer to the object model ideal. • In C++, the header and the implementation are two parts of a class, the header can contain some of the implementation, and all fields must be declared. • In Java, the interface and implementation are completely separate, the interface contains no implementation, and private and protected fields are not declared.
Java Inheritance • There are two key object oriented ideas that drive inheritance in Java, hook methods and template methods. In both cases, they give shape to a process that is initially incomplete and is completed by methods that inherit from or implement them.
Hook Methods • A hook method, usually an abstract method in an abstract class, is a place holder that will be filled with application specific logic in a later class that implements the method. • Java literature often refers to a hook method as a “hot spot,” but that term doesn’t always refer to a method. A hot spot can also be implemented as a class or even an application.
Template Methods • A template method contains a process flow detailing the steps to be done, but some of the implementation is left out, to be implemented from an abstract method or overridden in a method that inherits from the template. Templates are one of the “Gang of Four” patterns. They are different from hook methods because they give a structure to the task with partial implementation.
Contracts and Invariants • While I will not test you on the material in section 6.2 of the text, or require you to include contracts in your code, you need to understand this material, particularly preconditions and postconditions, in order to implement unit testing with JUnit. Starting with this chapter, I will also require you to use Javadocs to document your code, so understanding the Javadocs variables can improve your documentation. You can use Operation Contracts as your planning document, and/or use Contracts in your code as an alternative to that.
Assertions (Section 6.2.3) • While I will not require assertions in homework or test you on them, I would suggest that you try an assertion in a few of your homework assignments so that you can understand them as a useful tool. That understanding is also something that will help you use JUnit.
Canonical Form of Classes • Classes designed for general use should follow canonical form, including the following elements: • No-argument constructor • Object equality • String representation • Cloning • Serialization • All of these items take additional work, but it is rewarded with robust, maintainable and reusable code.
No Argument Constructor • Having a constructor without arguments (in addition to others that may require arguments) allows instances of a class to be created by the JVM at run time without the new operator. • Many Java applications and frameworks depend on the ability to load classes and create instances when an uninstantiated class is referenced at run time. • Dynamic loading is a key feature of Java.
Object Equality • Textbook section 6.3.2 gives a good explanation of the measures necessary so that subclasses that are instances of a superclass can be compared at the superclass level without the comparison failing because the subclass is a different type. • The comparison equality is more general than only at the superclass level, but that concept helps understand the purpose of comparability.
Hash Code • Since identical classes should generate identical hash codes, any general class that generates hash codes should be implemented in a way that objects that are the same should generate identical hash codes even if they are a subtype or implementation of the same interface.
Cloning Objects • Another operation that is problematic for subtypes and implementation is cloning. • How to make objects clonable is described in the text, section 6.3.4. • Notice the difference between a shallow copy that copies the references but points to the same list, and a deep copy that copies the list as well. (Next slide)
Shallow Copy Deep Copy Head Head Head Head Tail Tail Tail Tail Count: 3 Count: 3 Count: 3 Count: 3 1 1 1 2 2 2 3 3 3 Clones of a LinkedList list1 list1 list1.clone() list1.clone()
Serialization • Serialization transforms an object into a sequence of bytes. This allows objects to be saved to files or transferred across a network, and is another key feature of Java. • Classes that need to be stored in files or transferred over a network should implement the java.io.serializable interface. (Also see section 8.4.1 of the text)
Patterns • Continuing the discussion on object-oriented principles introduced in the last chapter, the author focuses on useful abstractions, particularly the use of software design patterns, in chapter 6.
Applying patterns • A house may involve many models, such as a landscape model, a framing model, an electrical wiring model, and a plumbing model. Over time, architects have learned that some designs are quite practical, such as a center hall colonial, while others tend to have severe limitations, such as an A-frame.
Design as philosophy • One of the most influential philosophers of structural design is Christopher Alexander, a retired professor of architecture at the University of California at Berkeley. • His ideas have also been applied to software design. See his web site at http://www.patternlanguage.com/leveltwo/ca.htm and select software from the left menu.
The Zen of Christopher Alexander • The Quality Without a Name (QUAN) • The essence of life and usefulness; freedom, harmony, wholeness, comfort, durability, adaptability • The Gate • How we reach the Quality; a living common pattern language; the universal “ether” of patterns and relationships in a domain • The Timeless Way • Apply patterns from the Gate by differentiating space in piecemeal growth into a live design with the Quality
Books on Patterns • Christopher Alexander • Notes on the Synthesis of Form, 1964 • The Oregon Experiment, 1975 • A Pattern Language: Towns, Building, Construction, 1977 • The Timeless Way of Building, 1979 • Software Patterns • Gamma, Helm, Johnson Vlissides, Design Patterns: Elements of Reusable Object Oriented Software, 1995 • Bushmann, Meunier, Rohnert, Sommerlad, Stahl, Pattern-Oriented Software Architecture: A System of Patterns, 1996 • Pattern Languages of Program Design (and PLOPD 2, 3, 4) 1995-1999 • Larman, Applying UML and Patterns, An Introduction to Object Oriented Analysis and Design, 1997
Testing • Chapter 6 introduces section 6.4 on unit testing. Since the homework will require you to use JUnit, see the supplemental lecture on testing with JUnit. JUnit comes integrated with the Net Beans and Eclipse development environments, and I recommend that you do the assignment in one of them.
Build and make tools • There is also a supplemental lecture on Ant to go with section 6.5. Most compilation commands in Java are very verbose, and typing the commands by hand can be very time consuming and error prone. An automated tool such as Ant is essential for productivity.
Review Questions • What does an accessor do? • What does a mutator do? • How are tests for equality different for strings than for other objects? ... than for operators? • What is serialization? • When and e\why do we separate an interface from an implementation?
Bibliography • (Books listed on patterns) • Jia, Xiaoping, Object Oriented Software Development Using Java. Addison Wesley, 2003