Project with classes:



Approaching a problem that will involve many classes - we need some kind of strategy, a plan or set of steps that will make a good basis for these kinds of problems.

Here is one set of steps that seems like it works for many such problems.
  1. List classes
    1. From specifications.
    2. Developing a good set of classes corresponding to general problem statement is often very subtle and is really something of an art.
    3. There typically is not only one good solution, and there is often not a BEST solution.
  2. Class hierarchy
    1. Decide on parent and child classes.
    2. You many need to change your mind about this as a project goes along, so don't think this is set in concrete.
  3. Attributes
    1. Which attributes should be where in the class hierarchy?
    1. Here you should consider moving attributes around in the class hierarchy.
    2. For example, if an attribute is common to ALL the children of a class, it would be a good idea to move that attribute to the parent class.
    3. Consider using classes already defined in the JDK. For example, when working with GUI's, extending JButton can be a nice solution.
  4. Types
    1. Give attributes types (int, double, String, some other class)
  5. Constructors
    1. Parameter lists
    2. Default no-parameter constructor
      1. Automatic
      2. BUT - will be hidden if there are any explicit constructors
      3. Hidden ones may cause problems in hierarchy since a child constructor may implicitly call the parent no-parameter constructor
    3. Consider Scanner constructors
    4. Consider super and this calls
  6. Methods
    1. public String toString () method in pretty much ALL classes
      1. use toString methods of parent classes as appropriate
    2. parameter lists
    3. consider parent versions with and over one in this class
    4. overriding and overloading
  7. Output
    1. Get output working
    2. We want to see results as soon as possible
  8. Data files?
    1. If the problem is larger, we want to work with data files quickly to check everything out
    2. Format:
      1. Decide on data file format -
      2. At least at first we want these to be as simple as possible
      3. Should include creating objects of each class
      4. Suggest one line in the file for each class
      5. Ignore lines that don't define one of the classes - this allows comments and convenient spacing in the file
      6. Since Scanner works with space delimiters, try to use space delimiters in the file
    3. Reading:
      1. Scanner to read the file line by line (hasNextLine, nextLine)
      2. Instantiate a new Scanner on that line
        1. Use that Scanner to process the line
        2. Create a new instance of the class defined on that line (switch is a good idea here)
        3. Pass the rest of the line Scanner to a constructor for that class
        4. In the constructor, pass the line Scanner reference to parent Scanner constructors as appropriate
        5. Use hasNext [int, double] and next [Int, Double] as appropriate
        6. May use exception handling - this can get rather complex and each get next type will have somewhat different exceptions
    4. Printing:
      1. System.out.println ("Read >" + v + "<");
        // cool way to check that line was read, and the constructors and toString methods are in harmony

Class Code Structure

So here is an outline of many of the common elements of a class.

[public] class <name> // public: name =, source code file may have other classes
[extends <some class>] // default is Object
[implements <some inteface(s)>] // we will talk more about later in this course
{ // start class body
  <static variables>
  <instance variables>
  <static methods>
  <instance methods>
  public String toString () {} // a REALLY GOOD IDEA in pretty much all classes
  [public static void main (String args []) {}] // may be a good idea in many classes
} // end class

Coding Sequence

  1. Create a parent class, something like:
    public class MyTestClass {
    } // end class MyTestClass
    1. Note that this is kind of trivial, but if you have errors here, there is no reason to go on writing code
  2. Add a main method.
  3. Add a simple output line, something like the following, and run it.
    System.out.println ("Bye");
  4. Add class declarations per design and requirements (see above for some thoughts about appropriate classes)
    Something like the following, just the barest outline:
    class MyClassA {}
    class MyClassB extends MyClass A {}
    1. This should compile, even if this does pretty nothing else
  5. Get some output:
    1. in each class - one at a time:
      1. create a toString method in a class
    2. in main
      1. instantiate the class
        MyClassA x = new MyClassA ();
      2. print out x using MyClassA toString method:
        System.out.println ("x: >" + x + "<");
  6. Declare appropriate attributes
    1. Types - each attribute should have a type, this is the time to nail those down
    2. Names - each attribute should have an appropriate name
    3. public vs private?
      1. if this is going to be a big project, it is a good idea to declare all the variables private and use getters and setters to control access to the variables.
      2. if you need security, it is a really good idea to implement right off the bat
  7. Initialize attributes
    1. null is ok for class references
    2. Default initial values
      1. for class static and instance variables is 0,
      2. but that can get confusing
      3. Suggestion: give each attribute some "junk" value, so if this value prints or shows up, you will know that some expected update to the value didn't happen
    3. Read values
      1. from console
      2. from a data file
  8. Check
    1. After every change, check the output
  9. After this framework has been assembled, you should be ready to pay attention to the operations specified by the requirements.
    1. You can think of the items 1-8 here as laying a solid foundation for the rest of your project.

Example GUI

import javax.swing.*;
import java.awt.*;

public class GUI_01 extends JFrame {
  public GUI_01 () {
    this ("one");
  } // end no parameter constructor

  public GUI_01 (String t) {
    setTitle (t);
    setSize (200,200);
    setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo (null);
    add (new JButton ("North " + t), BorderLayout.NORTH);
    add (new JButton ("East " + t), BorderLayout.EAST);
    add (new JButton ("West " + t), BorderLayout.WEST);
//     validate ();
    pack ();
    setVisible (true);
  } // end String constructor

  public static void main (String args []) {
    GUI_01 ga = new GUI_01 ();
    GUI_01 gb = new GUI_01 ("two");
  } // end main

} // end class GUI_01

Example Person/Student/Employee/Name

public class School {
  public static void main (String args []) {
    Name n = new Name ();
    Name m = new Name ("Jane", "Doe");
    Student st = new Student ("Harry", "Potter", 38);
    System.out.println ("Student: >" + n + "<");
    System.out.println ("Student: >" + m + "<");
    System.out.println ("Student: >" + st + "<");
    System.out.println ("bye");
  } // end main method
} // end class School

class Name {
  String name = "Fred";
  public Name () { }
  public Name (String f, String l) {
    name = f + " " + l;
  } // end String String constructor
  public String toString () {return name;}
} // end class Name

class Person {
} // end class Person

class Student extends Person {
  Name n = new Name ("a", "b");
  int credits;
  public Student (String fn, String ln, int cr) {
    credits = cr;
    n = new Name (fn, ln);
  } // end String,String,int constructor
  public String toString () {
    return n + " " + credits;
  } // end method toString
} // end class Student

class Employee extends Person {
} // end class Employee

By: Nicholas Duchon
Updated: May 16, 2017