Programmierpraktikum




Claudius Gros, SS2012

Institut für theoretische Physik
Goethe-University Frankfurt a.M.

Object-Oriented Programming (OOP)


object-oriented programming

principles

classes and objects

public class MyClass {

int myVariable1;         // member variables can be
double[] myVariable2;    // private, public, static, ...

/** Define any number of member functions (methods).
  * They can have as return values any primitive data type or
  * any predefined or user defined object, or nothing (void).
  */
  void myFunction1 () {
  } // end of MyClass.myFunction1()

}   // end of class MyClass

object definition example: BookBasics

public class BookBasic {

  private int itemCode; // Internal variables.
  private String title;

/* Standard getter for itemCode.
 */
  public int getItemCode() {
    return itemCode;
  }

/* Standard setter for itemCode, returns 'true' if
 * itemCode is valid, otherwise 'false'.
 */
  public boolean setItemCode (int newItemCode) {
    if (newItemCode > 0) {   // a given constraint
      itemCode = newItemCode; 
      return true;
    } else 
      return false;
  }

/* Standard getter for title.
 */
  public String getTitle() {
    return title;
  }

/* Standard setter for title.
 */
  public void setTitle (String newTitle) {
    title = newTitle;
  }

/* Non-trivial member function.
 */
  public void display() {
    System.out.println(itemCode + " " + title);
  }
} // end of class BookBasic 

object definition usuage: BookBasics

public class UseBookBasic {

  public static void main(String[] args) {
    BookBasic b = new BookBasic();      // instantiation of a book
    b.setItemCode(5011);                // code of book
    b.setTitle("Fishing Explained");    // book title

// --- printing by hand and using the printing routine of BookBasic
    System.out.println(b.getItemCode() + " " + b.getTitle());
    System.out.print("From BookBasic.display(): ");
    b.display(); 
  }
}  

// *** *************** *** 
// *** class BookBasic *** 
// *** *************** *** 

class BookBasic {
     
  private int itemCode; 
  private String title;
     
  public int getItemCode() { return itemCode; }
     
  public boolean setItemCode (int newItemCode) {
    if (newItemCode > 0) {   
      itemCode = newItemCode; 
      return true;
    } else 
      return false;
  }
     
  public String getTitle() { return title; }
     
  public void setTitle (String newTitle) {
    title = newTitle;
  }
     
  public void display() {
    System.out.println(itemCode + " " + title);
  }
} 

Java access modifiers

class constructors

public class BookWithConstructor {

  private int itemCode;
  private String title;

/* User defined constructor.
 */
  public BookWithConstructor(int newItemCode, String newTitle) {
    setItemCode(newItemCode);   // use always the setter if existing,
    setTitle(newTitle);         // there might be contraints 
  }

  public int getItemCode() {
    return itemCode;
  }
  public boolean setItemCode (int newItemCode) {
    if (newItemCode > 0) {   
      itemCode = newItemCode; 
      return true;
    } else 
      return false;
  }
  public String getTitle() {
    return title;
  }
  public void setTitle (String newTitle) {
    title = newTitle;
  }
  public void display() {
    System.out.println(itemCode + " " + title);
  }
}

class instantiation

public class UseBookWithConstructor {

  public static void main(String[] args) {
    BookWithConstructor b = 
      new BookWithConstructor(5011, "Fishing Explained");
    b.display();
  }
}

// ********************************* 
// *** class BookWithConstructor ***
// ********************************* 

class BookWithConstructor {

  private int itemCode;
  private String title;

/* User defined constructor.
 */
  public BookWithConstructor(int newItemCode, String newTitle) {
    setItemCode(newItemCode);
    setTitle(newTitle);
  }

  public int getItemCode() {
    return itemCode;
  }
  public boolean setItemCode (int newItemCode) {
    if (newItemCode > 0) {   
      itemCode = newItemCode; 
      return true;
    } else 
      return false;
  }
  public String getTitle() {
    return title;
  }
  public void setTitle (String newTitle) {
    title = newTitle;
  }
  public void display() {
    System.out.println(itemCode + " " + title);
  }
}

method overloading (polymorphism)

public class BookMultiConstructor {
  private int itemCode;
  private String title;

/* The first constructor.
 */
  public BookMultiConstructor(int newItemCode, String newTitle) {
    setItemCode(newItemCode);
    setTitle(newTitle);
  }

/* The second constructor.
 */
  public BookMultiConstructor(String newTitle) {
    setItemCode(0);
    setTitle(newTitle);
  }

  public int getItemCode() {
    return itemCode;
  }
  public boolean setItemCode (int newItemCode) {
    if (newItemCode > 0) {   
      itemCode = newItemCode; 
      return true;
    } else 
      return false;
  }
  public String getTitle() {
    return title;
  }
  public void setTitle (String newTitle) {
    title = newTitle;
  }
  public void display() {
    System.out.println(itemCode + " " + title);
  }
}

public class UseBookMultiConstructor {
  public static void main(String[] args) {

    BookMultiConstructor b = 
       new BookMultiConstructor(5011, "Fishing Explained");
    b.display();
    // note the immediate call to a method on a new instance
    new BookMultiConstructor("Dogs I've Known").display();
  }
}

static functions

public class MyUtilityDemo {

public static void main(String[] args) 
  {
  double rr = 11.123456;
  MyUtility.printString("initial rr: " + String.valueOf(rr));
  rr = MyUtility.roundToDigits(rr, 2);
  MyUtility.printString("  2 digits: " + String.valueOf(rr));
  }  // end of MyUtilityDemo.main()

}    // end of class MyUtilityDemo

// *** *************** ***
// *** class MyUtility ***
// *** *************** ***

/** Example of a abstract (cannot be instantiated) class.
  * An abstract class can have only static member functions.
  */
abstract class MyUtility {

/** Just printing a String to standard ouput.
  * Can be generalized to print (append) data to a file.
  */
static void printString(String output)
 {
 System.out.println("MyUtility.printString():: " + output);
 }

/** Rounds to n digits accuracy.
  */
static double roundToDigits(double input, int nDigits)
 {
 for (int i=0; i<nDigits; i++)
   input *= 10.0;
 input = Math.round(input);
 for (int i=0; i<nDigits; i++)
   input *= 0.1;
 return input;
 }

}   // end of class MyUtility

extending and inheriting

public class ExtendingDemo {

public static void main(String[] args) {

  System.out.println(" ");

  ExtendingSimpleClass esc = new ExtendingSimpleClass(3);
  System.out.printf("calling ExtendingSimpleClass.getTopSecret()  : %d\n",
                     esc.getTopSecret()); // inherited from SimpleClass
  System.out.printf("calling ExtendingSimpleClass.secretPrinting(): ");
                     esc.secretPrinting();

// --- an ExtendingSimpleClass is a SimpleClass
  SimpleClass sc = new ExtendingSimpleClass(4);
  int dummy = sc.getTopSecret();               // possible
//            sc.secretPrinting();             // error
  ((ExtendingSimpleClass)sc).secretPrinting(); // possible: casting beforehand to subclass

// --- all classes are objects
  Object o1 = new ExtendingSimpleClass(5);
  Object[] o2 = new String[7];

  }  // end of ExtendingDemo.main()
}    // end of class ExtendingDemo

// *** ************************** ***
// *** class ExtendingSimpleClass ***
// *** ************************** ***

class ExtendingSimpleClass extends SimpleClass {

public ExtendingSimpleClass(int topSecret)
 {
 super(topSecret);             // calls the constructor of the parent class
 }
public void secretPrinting()
 {
 System.out.printf("printing from ExtendingSimpleClass: %d\n\n",getTopSecret());
 }
}   // end of class ExtendingSimpleClass

// *** ***************** ***
// *** class SimpleClass ***
// *** ***************** ***

class SimpleClass {
private int topSecret;                                           // a private variable
public SimpleClass(int topSecret){ this.topSecret = topSecret; } // a constructor
public int getTopSecret(){ return topSecret; }                   // a standard getter
}   // end of class SimpleClass

the main method

public class MainDemo {

/** A static variable counting the number of times main() was called.
  */
public static int counter = 0;

/** A non-static variable, can only be accessed when 
  * MainDemo has been instatiated.
  */
public String myName;

/** Constructor for MainDemo,
  * this.myName refers to the member variable of the
  * current (this) instantion.
  */
public MainDemo()
  {
  this.myName = "I am class number " + MainDemo.counter;
  }

/** The main() function is called when starting.
  * Per definitions it has an String array as argument.
  */
public static void main(String[] args) 
  {

// note the two ways to access: 
// MainDemo.counter : always possible
//          counter : only from inside MainDemo
  MainDemo.counter++;
  System.out.printf("number of times main() was called: %d\n",counter);

// MainDemo itself can be instatiated
  MainDemo newMainDemo = new MainDemo();
  System.out.printf("              name of newMainDemo: %s\n",
                    newMainDemo.myName);

// the main method is static and can be called
// with a string array as an argument,
// the if-condition avoids an infinite recursion loop
  if (MainDemo.counter < 7)
    MainDemo.main(new String[2]);

  }  // end of MainDemo.main()
}  // end of class MainDemo

objects of objects

public class ObjectOfObjects {

/** Escape sequences for colored console output,
  * may be operating system dependent.
  * Just for the fun of it.
  */
public static final String ANSI_BLACK   = "\u001B[30m";
public static final String ANSI_RED     = "\u001B[31m";
public static final String ANSI_GREEN   = "\u001B[32m";
public static final String ANSI_YELLOW  = "\u001B[33m";
public static final String ANSI_BLUE    = "\u001B[34m";
public static final String ANSI_MAGENTA = "\u001B[35m";
public static final String ANSI_CYAN    = "\u001B[36m";
public static final String ANSI_WHITE   = "\u001B[37m";
public static final String ANSI_RESET   = "\u001B[m";

public static void main(String[] args)
  {

// --- create array of ColoredObject
  ColoredObject[] manyObjects = new ColoredObject[3];

// --- instantiate the individual array elements
  manyObjects[0] = new ColoredObject("I am red (hopefully) ",
                                     ObjectOfObjects.ANSI_RED);
  manyObjects[1] = new ColoredObject("sure, but I am green ",
                                     ObjectOfObjects.ANSI_GREEN);
  manyObjects[2] = new ColoredObject("yes, but blue is best",
                                     ObjectOfObjects.ANSI_BLUE);

// --- print colored objects line by line
// --- ANSI_RESET resets the output color
  System.out.println(" ");
  for (int i=0; i<manyObjects.length; i++)
    {
    String outString = manyObjects[i].getColor()
                     + manyObjects[i].getText()
                     + ObjectOfObjects.ANSI_RESET;
    System.out.println(outString);
    }
    
  System.out.println(" ");
  System.out.println("and I am boring black (again)");
  System.out.println(" ");

  }  // end of ObjectOfObjects.main()
}  // end of class ObjectOfObjects

// *** ******************* ***
// *** class ColoredObject ***
// *** ******************* ***

class ColoredObject {

private String myAnsiColor;
private String myText;

public ColoredObject(String text, String color)
  {
  this.myText = text;
  this.myAnsiColor = color;
  }

public String getColor(){return this.myAnsiColor;}
public String getText(){return this.myText;}

}  // end of class ColoredObjects

reference to objects

public class ReferenceDemo {

public static void main(String[] args) 
  {

// aInt and bInt are two distinct integer variables
  int aInt = 1;
  int bInt = aInt;
  System.out.printf("aInt, bInt:  %d | %d\n",aInt,bInt);
  bInt = 2;
  System.out.printf("aInt, bInt:  %d | %d\n",aInt,bInt);
  System.out.println(" ");

// bArray is a synonym for aArray 
// bArray is not a new object
  int[] aArray = { 1, 2, 3};
  int[] bArray = aArray;
  System.out.printf("aArray: %d %d %d\n",aArray[0],aArray[1],aArray[2]);
  System.out.printf("bArray: %d %d %d\n",bArray[0],bArray[1],bArray[2]);
  System.out.println(" ");
  
  aArray[0] = 0;
  System.out.printf("aArray: %d %d %d\n",aArray[0],aArray[1],aArray[2]);
  System.out.printf("bArray: %d %d %d\n",bArray[0],bArray[1],bArray[2]);
  System.out.println(" ");

  bArray[2] = 7;
  System.out.printf("aArray: %d %d %d\n",aArray[0],aArray[1],aArray[2]);
  System.out.printf("bArray: %d %d %d\n",bArray[0],bArray[1],bArray[2]);
  System.out.println(" ");

// String operations always create new String objects
  String aStr = "a comes first";
  String bStr = aStr;           // a new String object is created implicitly
  System.out.printf("aStr, bStr:  %s | %s\n",aStr,bStr);

// creating a new String object 'b comes second' and
// assigning its reference to the variable bStr 
  bStr = "b comes second";
  System.out.printf("aStr, bStr:  %s | %s\n",aStr,bStr);
  System.out.println(" ");

  }  // end of ReferenceDemo.main()
}  // end of class ReferenceDemo

call by value / call by reference

call by value
When a function f(arg) is called only the value of the argument arg is passed, not its references.
Changes of the argument inside the function f() do not change the value of the argument outside of the function.

call by reference
When a function f(arg) is called only the reference of arg is passed to the function.
Changes of the argument inside the function f() do change the value of the argument outside of the function.

JAVA

public class FunctionCallDemo {

/** Changing the value of a primitive data type has
  * has no effect outside the residing function,
  * call-by-value only passes the value and not the
  * reference of a primitive data type.
  */
public static void callByValue(int inputInteger)
  {
  System.out.printf("in FunctionCallDemo.callByValue(), "
                   + "inputInteger : %d\n",inputInteger);
  inputInteger = 0;
  }

/** Only the reference, not the value, of Objects are
  * passed to the function, creating a synonym of the argument.
  */
public static void callByReference(int[] inputArray)
  {
  inputArray[0] = 0;
  }

public static void main(String[] args) 
  {

// --- call by value, for primitive data types
  int callInteger = 10;
  System.out.println("  ");
  FunctionCallDemo.callByValue(callInteger);
  System.out.printf("       in FunctionCallDemo.main(), "
                   + " callInteger : %d\n",callInteger);
  System.out.println("  ");

// --- call by value, for objects
  int[] callArray = { 33, 44, 55};
  System.out.printf("       in FunctionCallDemo.main(), "
                   + "   callArray : %2d %2d %2d\n",
                   callArray[0], callArray[1], callArray[2]);
  FunctionCallDemo.callByReference(callArray);
  System.out.printf("       in FunctionCallDemo.main(), "
                   + "   callArray : %2d %2d %2d\n",
                   callArray[0], callArray[1], callArray[2]);

  }  // end of FunctionCallDemo.main()
}  // end of class FunctionCallDemo

classes and files

one file per class

one program per file

public class MyProgram {

public static void main(String[] args) 
  {
  MyClass mc = new MyClass();
// ...
  }  
}   

// *** ************* ***
// *** class MyClass ***
// *** ************* ***

class MyClass {
// ...
}   

interfaces

interface MovingHero {

public String getSymbol();       // symbol of hero
public int getPosition();        // position of hero
public void move();              // move the hero
public void invertDirection();   // invert direction of movement

} 

interface demo - inline battle

public class InterfaceDemo {

/** The length of the battlefield.
  */
public static final int length = 30;

public static void main(String[] args) 
                   throws Exception 
  {

// -- create array of hero (interfaces, not classes
  MovingHero[] allHeros = new MovingHero[2];

// -- instantiate the heros, with classe now
  allHeros[0] = new BlueHero(InterfaceDemo.length);
  allHeros[1] = new RedHero(InterfaceDemo.length);

// -- the configuration of the heros on the battlefield
  String[] heroPos = new String[InterfaceDemo.length];

  System.out.println(" ");

// -- let the heros battle each other
  for (int i=0; i<100; i++) 
    {
    for (int h=0; h<heroPos.length; h++)         // empty battlefield
      heroPos[h] = " ";
    for (int a=0; a<allHeros.length; a++)        // loop over all heros
      {
      int pos = allHeros[a].getPosition();
      if (heroPos[pos].equals(" "))
        heroPos[pos] = allHeros[a].getSymbol();  // draw hero
      else 
        allHeros[a].invertDirection();           // invert if colliding
      allHeros[a]. move();                       // move them
      }
    
    for (int l=0; l<heroPos.length; l++)         // print battlefield
      System.out.printf("%s",heroPos[l]);

// --- no linebreak, return to beginning of line
    System.out.print("\r");

// --- pause the program execution (ms)
    Thread.sleep(200);  
//
    } // end of loop over all steps


  } // end of InterfaceDemo.main()
} // the dof class InterfaceDemo

// *** ********************** ***
// *** Interface moving heros ***
// *** ********************** ***

/** Any here hero is a moving hero.
  */
interface MovingHero {

public String getSymbol();       // symbol of hero
public int getPosition();        // position of hero
public void move();              // move the hero
public void invertDirection();   // invert direction of movement

}  // end of interface MovingHero

// *** ************** ***
// *** class red hero ***
// *** ************** ***

class RedHero implements MovingHero {

private static final String mySymbol = "\u001B[31m" + "\u0040" + "\u001B[m";
private int myPos;
private int mySpeed = 2;
private int length;

public RedHero (int length)
  {
  this.myPos = (int)(Math.random()*length);
  this.length = length;
  }

public String getSymbol()    
  {
  return this.mySymbol;
  }
public int getPosition()
  {
  return this.myPos;
  }
public void move()
  {
  this.myPos = (this.myPos+this.mySpeed+this.length)%this.length;
  }
public void invertDirection()
  {
  this.mySpeed *= -1;
  }

}  // end of class RedHero

// *** *************** ***
// *** class blue hero ***
// *** *************** ***

class BlueHero implements MovingHero {

private static final String mySymbol = "\u001B[34m" + "\u0026" + "\u001B[m";
private int myPos;
private int length;

public BlueHero (int length)
  {
  this.myPos = (int)(Math.random()*length);
  this.length = length;
  }

public String getSymbol()    
  {
  return this.mySymbol;
  }
public int getPosition()
  {
  return this.myPos;
  }
public void move()
  {
  this.myPos = (this.myPos + 1)%this.length;
  }
public void invertDirection()
  {
  }

}  // end of class BlueHero