Flow control: methods

Dr Andy Evans

[Fullscreen]

Review

  • To make a variable we make the label in memory, then attach something to it.
  • We can make an object variable using a particular class:
    	
    ClassName objectName = new ClassName();
    
    
  • We can access code inside an object using the dot operator:
    	
    objectName.variable = 10;
    double x = objectName.variable;
    
    
  • But how do we run code in other classes?

Running code

  • We already have!
    	
    System.out.println("Hello World");
    
    
    This is running the code called "println()".
  • Not only does this run code, but it seems to send the code some data ("Hello World") which it does something with.
  • Note that we tell code from variables because code is always followed by parentheses, even if there is no data involved.
  • Why and how would we do this?

Why

  • We divide code between classes to match a key idea in Object Orientated design: Encapsulation. One aspect of this is that data and the methods to work on it should be in the same class so they are easily added or replaced. Classes should deal with just one thing. This means we must have some way of running code in other classes.
  • Within a class we want to separate the code into different functional units:
    1. enhances encapsulation by providing toolkits of code to deal with specific data;
    2. easier to maintain;
    3. easier to check.
  • Also means that if we want to repeat code in different places (where a loop wouldn't help), we can just call the chunk of code.

How?

  • Such a chunk of code is called a method.
  • We've already used one:
    	
    System.out.println("Hello World");
    
    
  • And, more surprisingly, we've already written one ourselves, the 'main' method:
    	
    public static void main (String args[]) {
    }
    
    

Code structure

  • Almost all of the code in classes must be within methods.
  • Methods cannot be nested (easily).
  • Code runs by processing a series of methods.
  • Each method is called by another method in turn, or, in the case of user interaction, by methods in the JVM.
  • Processing can't magically skip to methods that aren't called - calling methods is the only thing that structures the code execution at this scale - if you want a method to run, you have to call it from somewhere.

Example use

	
public class HelloWorld {
    public static void main (String args[]) {
		System.out.println("Hello World");
    }
}

  • This calls the println method and runs it.
  • The println method almost certainly calls other methods inside other classes we didn't write in order to do its job.
    (don't worry about these classes for the moment - you get these invisibly and for free with the java language, like System)
  • Processing cascades through the program by methods calling other methods in other classes.

Example method

	
public class Point {

    double x = 0.0; 
	
    void incrementX() {
		x++;
    }
}

  • void incrementX() is the method declaration.
  • Variable names are lower-case starting camelCase.
  • We'll come back to void.
  • Note that variables set up when this class is turned into an instance (i.e. an object) are the only running code outside of methods.
  • This means their scope is throughout the code, including the method.

Using our example

	
public class PointUser {
    public static void main (String[]args) { 
	
		Point pt1 = new Point();
		pt1.incrementX();
		
    }	
}

  • pt1.incrementX() is the method call.
  • Note that we usually have to make an object to use either variables or methods inside them (we'll come back to System).
  • Note that the x variable within the pt1 object is created when it is instantiated.

Code structuring

  • Classes are composed of instance variables and one or more sets of unnested methods:
    	
    public class Point {
        
        double x = 0.0;
        double y = 0.0;
    
        void incrementX {
    		x++;
        }
    	
        void incrementY {
    		y++;
        }
    }
    
    

Methods

  • Methods are like tools in a toolkit.
  • In addition to just running code, as here, they can also take in and return data.
  • In previous slides, void in the declaration means nothing is returned.

Return values

	
public class Point {
    double x = 0.0;

    boolean isXGreaterThanZero() {
		if (x > 0) {
		    return true;
		} else {
		    return false;
		}
    }
}

  • The return type of the method must match the thing returned.
  • All paths through the method must return something, or the compiler will complain.

Example use

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

		Point pt1 = new Point();
		boolean answer;
		answer = pt1.isXGreaterThanZero();

    }
}

Good returns

  • Because something is being returned, you have to do something with it:

     

  • Attach a label for later use:
    	
    boolean answer = pt1.isXGreatThanZero();      
    System.out.println(answer);
    
    
  • Use the data immediately:
    	
    if (pt1.isXGreatThanZero()) {
    
    
    	
    System.out.println(pt1.isXGreatThanZero());
    
    

Bad returns

  • But don't leave it hanging in mid-air:
    
    Point pt1 = new Point();
    pt1.isXGreaterThanZero(); // Noooooo....
    
    
  • The computer just sees this as:
    	
    Point pt1 = new Point();		
    false;
    
    
    or whatever value it is. This isn't code, it means nothing.

Passing data in

  • You can also pass data in to be used or worked on:
    	
    public class Point {
        double x = 0.0;
    
        void addToX(double value) {
    		x = x + value;
        }
    
    }
    
    
  • Note that double value is making a label that we attach to the number passed in.

Example use

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

		Point pt1 = new Point();
		pt1.addToX(10.0);

    }
}

  • Note that we're not getting anything back here. The return type was void.

Multiple values

  • We can pass in multiple values, and of different types:
    	
    void addToX(double value1, int value2) {
        x = x + value1 + value2;
    }
    
    
  • Use:
    	
    pt1.addToX(10.0, 20);
    
    

Parameters and arguments

  • Note that the arguments sent in are allocated to the parameter variables in order.
  • Types must match up:
    	
    pt1.addToX(10.0, 20);	
    void setData (double value1, int value2) {
    
    

All together now

  • You can get methods that return or take in nothing.
  • You can get methods that return but take in nothing.
  • You can get methods that take in, but don't return.
  • You can get methods that take in and return.

Receiving and returning

	
public class Point {
    double x = 0.0;

    boolean isXGreaterThan (double value) {
		if (x > value) {
		    return true;
		} else {
		    return false;
		}
    }
}

Example use

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

		Point pt1 = new Point();
		boolean answer = 
		    pt1.isXGreaterThan(10.0);

    }
}

  • Note that while we can take in multiple things we can only return one thing.

Object arguments

  • There's nothing to stop objects as arguments / returns:
    	
    pt2.x = 100.0;
    Point pt3 = pt1.calcHalfWayTo(pt2);	
    
    
    	
    Point calcHalfWayTo (Point pointIn){
    
        double distBetween = (x - pointIn.x);
        Point halfWay = new Point();
        halfWay.x = x + (distBetween / 2.0); 
        return halfWay;
    	
    }
    
    

Array arguments

  • There's nothing to stop arrays as arguments / returns:
	
int[][] ans = pt1.addXToIntArray(intArray);


int[][] addXToIntArray (int[][] arrayIn){

    int [][] temp = 
		new int[arrayIn.length][arrayIn[0].length];
		
    for (int i = 0; i < arrayIn.length; i++) {
		for (int j = 0; j < arrayIn[i].length; j++) {
		
		    temp[i][j] = arrayIn[i][j] + x;
			
		}
    }
	
    return temp;		
}

Assignment to variables

	
// main class
int a = 10;
int b = someObject.change(a);






System.out.println("a = " + a);
System.out.println("b = " + b);




->




<-


	
// other class



int change (int c) {
    c = 20;
    return c;
}


 

  • Prints:
    	
    a = 10
    b = 20
    
    
  • Even though it looks like the value 'a' points at has change, actually 'c' gets a copy of the value.

Assignment to variables

		
// main class
objA.x = 10;
objB = 
  someObj.change(objA);







System.out.println
	("objA.x = " + objA.x);
System.out.println
	("objB.x = " + objB.x);




->





<-




	
// other class



SomeClass change 
	(SomeClass objC) {
    objC.x = 20;
    return objC;
}




 

  • Prints:
    	
    objectA.x = 20
    objectB.x = 20
    
    
  • Here, the value does change, everywhere.

Polymorphism

  • Having methods that take in multiple types.
  • Implemented through overloading.
  • You can call methods that do similar things the same name. The JVM will decide which is to be used on the basis of what is passed in.
  • For example:
    System.out.println("2");
    System.out.println(2);
    System.out.println(false);
    All called using System.out.println(someThing)
  • Note that if a method doesn't exist, the JVM will try an implicit cast. If this fails you'll get an error.

Review

There's a lot here, but it is important.
Work on the basics:
  • Writing and running a method that "Hello World"s.
  • Writing and running a method that takes in a String and prints it.
  • Writing and running a method that returns a String for you to print.
  • Then come back and look at these slides again.