/* An Incremental Tutorial to Object Oriented Programming in Java Chuck Liang Hofstra University Computer Science You've now learned some of the basic mechnisms and principles of program construction. You learned how to declare variables, use values of different types (int, double, etc...), if-else statements, basic input/output, etc ... Most importantly of all, you were told that programs are structured entities comprising of modular, localized components. We now expand on this idea in introducing formally the manner in which a modern "object oriented" program is organized. This will require you to understand several inter-related concepts and constructs fairly quickly. I will try to present these concepts and constructs in an incremental manner, but you should be aware that it will take a good deal of effort and willingness to "think in a new way" on your part. A program consists of many capabilities distributed among objects. Each object is a "server" that offers a set of services to its clients. For example, when you invoked brush.drawLine(x0,y0,x1,y1); brush.setColor(Color.green); in your stick figure program, the element "brush" is an object that offers you the services "drawLine" and "setColor". When you invoke these "methods", you are being a "client" to the brush server object. The values x0, y0, x1, y1, and the built-in value Color.green, are "parameters" passed to the methods. You've only been client so far. Now it's time to learn how to create your own objects with their own set of services. To create objects, you must first create a template or blue-print of the object - that way you can make as many as you want from the template. This template is called a "class". Inside the class, you specify the services that objects of this class will offer in the form of "methods" or "functions". Each method or function is a self-contained program enclosed by its own set of curly braces { and }. There are many kinds of functions, and we will look at the following categories in turn. Each successive category represents a new level of thinking that you must learn to attain: 1. functions that take no parameters and return no values 2. functions that take no parameters but returns some value 3. functions that can take parameters 4. functions that include local variables 5. functions that include non-local variables. A function of the first category is simply a block of code that is executed each time it's called. The first example I give will be an abstract overview: class SampleClass // begins class definition for SampleClass { public void f() { System.out.println("you have invoked the f method"); } // end of f public void g() { System.out.println("you have invoked the g method"); } // end of f } // end of class SampleClass public class whatever { public static void main(String[] args) { SampleClass myobject; //1 declares a SampleClass variable myobject = new SampleClass(); //2 creates instance of SampleClass myobject.f(); //3 calls f method of object myobject.g(); //4 calls g method of object myobject.f(); //5 calls f method of object again } // main } // public class whatever The class definition SampleClass defines two methods, f and g. These methods can be invoked from anywhere in your program (hence the keyword "public"). These are examples of functions that take no parameters, and return no values (hece the keyword "void"). The output of this program will be: you have invoked the f method you have invoked the g method you have invoked the f method The first line in main declares a variable called "myobject". If we wanted myobject to be an integer, we would have of course said "int myobject;". But here I want myobject to be a variable whose value is an object created from the SampleClass template. Declaring a variable doesn't give it a value. To assign a value to myobject we must create an "instance" of the SampleClass class, or in other words, a specific SampleClass object. This is accomplished using the keyword "new" as show on the second line in main. The third and fourth lines in main invokes or "calls" the methods f() and g() of myobject - the "." seperates the name of the object and the name of the method. The parentheses () after f and g are necessary to distinguish function names from ordinary variable names. Functions can be called multiple times as illustrated by line 5 in main. There are two important distinctions to note here (SO NOTE THEM!): 1. The distinction between a class (SampleClass) and an object (instance) of that class. The class is a template from which we can create many objects of the same type (I'll explain why we want more than one later). SampleClass is the class. myobject is the object or instance. SampleClass is in effect a new "type" you're defining yourself in addtion to the built-in types int, double, String, boolean, etc ... myobject is a variable to which you assign something of this type created via the "new" operation. 2. The distinction between defining a function and calling a function. The lines containing f() and g() inside the class definition *defines* the functions (or methods) f and g. Inside main, the statements involving f() and g() are functions calls. Note the difference in syntax! You don't use the keywords "public void" when calling a function, only when declaring it: "void" means that the function is a statement as opposed to an expression. The following is another example which we will make more and more complicated as we introduce more ways of writing classes and functions. */ /* Class with functions that return no values and take no parameters */ class waiter { // services are defined in the form of methods (functions): public void morenapkins() { System.out.println("here are more napkins for you!"); } public void water() { System.out.println("We don't have water!"); } public void menu() { System.out.println("chicken sandwich: $5.95"); System.out.println("burger: $4.95"); System.out.println("fries: $1.95"); } public void check() { System.out.println("Here's your check. Pay up!"); } } // end of class waiter public class objects0 { public static void main(String[] args) { int x; // declares an integer variable x = 5; // assigns integer variable a value waiter ourwaiter; // declares a waiter variable ourwaiter = new waiter(); // assigns variable a waiter object ourwaiter.water(); // executes statements in water() method ourwaiter.menu(); // executes statements in menu() method ourwaiter.check(); // executes statements in check() method } // end of main } // end of class objects0 /* LOCAL VARIABLES The body of each function (i.e. the statements inside its braces) can consist of any of the statements you've been using to write programs so far, including variable declarations. However, if you declared a variable inside a function, such as with the statement int x; this variable is only usable within this function. You cannot refer to this variable anywhere in your program outside of the body of this function - in other words, outside of the curly braces in which the declaration statement exists. If you declare int x; again in another function, it will be a DIFFERENT VARIABLE. They will be associated with different memory cells, and changing one will not affect the other. For example, consider the program class SampleClass { public void f() { int x; x = 3; System.out.println(x); } // f } // SampleClass public class whatever { public static void main(String[] args) { int x; x = 5; SampleClass myobject; // declares var myobject = new SampleClass(); // assign var to an instance myobject.f(); // calls myobject function System.out.println(x); } // main } // whatever This program will print 5 followed by 3. The assignment of x to 5 inside the function f did not affect the value of x inside main! When we execute the statement x = 5; inside the body of the f function, the "x" referred to is not the same variable as the "x" inside main! Each time the function f is called, the computer allocates new memory space to x, just as each time you start a program, the computer allocates memory to all your variables in the "main" function. Each function is like a small program. The variable "x" inside "main" never changed, and thus it printed as 3 even after the "x" inside f was set to 5. It's like having two streets both named "Lincoln Avenue" in two different cities. They may have the same name but they are in fact different streets. Think of it another way: you are collaborating with a friend of yours to write a program together. You've agreed that each of you will write a function that implements about half of the capabilities of the program. Each function is a self-contained, autonomous program in its own right, with its own set of variables. If you write a statement that changes a variable "x" in your function, you don't want to have to worry about whether it would have consequences in your friend's function. You may want to use "x" in your program for one purpose, while your friend may want to use "x" for an entirely different purpose. For example, you may want to use "x" to represent the x-coordinate of a point, while your friend may be using it to represent the radius of a circle. It's really not meant to be confusing! Rather it allows us to break down the task of writing a large program into smaller tasks of writing individual functions one at a time. Think about it, if changing "x" inside the function f did change the variable "x" in main, then I would have to look at an entire program, which could be tens of thousands of lines long, in order to trace the program and understand all the consequences of each statement! I won't be able to look at any portion of my program in isolation - I won't be able to look at my program as a collection of modular components. */