Java by Example - introducing classes and objects

back 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 next

You will heard the buzzword OOP, or "Object Oriented Programming" before, but maybe you don't know exactly what it means yet. The following examples are supposed to shed some light onto that mystery. Have a look at the following, not object oriented example applet. Click somewhere inside the applet to paint a bubble with random diameter and color. The bubble is defined inside the main class and is totally dependent from every modification you might do to the main class code.

//Sourcecode

import java.awt.*;
import java.applet.*;

//bubbles applet without bubble class

public class Project22 extends Applet
{
    Image Buffer;
    Graphics gBuffer;

    public void init()
    {
        Buffer=createImage(size().width,size().height);
        gBuffer=Buffer.getGraphics();
    }

    public boolean mouseDown(Event evt,int x,int y)
    {
        drawRandomBubble(x,y);

        repaint();

        return true;
    }

    public void drawRandomBubble(int x, int y)
    {
        int red=(int)(Math.random()*255);
        int green=(int)(Math.random()*255);
        int blue=(int)(Math.random()*255);

        Color randomColor=new Color(red, green, blue);

        gBuffer.setColor(randomColor);

        //generate a random number between 10 and 100
        int diameter=(int)(Math.random()*90)+10;

        //make mouse cursor the center of our random bubble
        gBuffer.fillOval(x-diameter/2,y-diameter/2,diameter,diameter);
    }

    public void update(Graphics g)
    {
        paint(g);
    }

    public void paint(Graphics g)
    {
        gBuffer.setColor(Color.black);
        gBuffer.drawString("Click the applet to paint bubbles!", 50,20);
        g.drawImage (Buffer,0,0, this);
    }
}

This next applet uses a separate "Bubble" class (which is also a separate *.class file after compilation). This class is a kind of "black box" for the rest of the program. It has it's own variables and methods. To use a class, the program must create an instance, or "object" of that class: Bubble myBubble; and myBubble = new Bubble(x,y);. The first declared a variable name for our object, the second created the object itself. The arguments (x,y) are the arguments of the constructor. The constructor is a method that is called from the creating class in the moment an object is created. You can pass arguments from the creating class to the object here, or make any initializations for the new class. A class can have several constructor methods, that are distinguished by the type and number of arguments. Via that object (you can create as much as you need), the program can call methods of that class. Use the "." operator between object name and method name to access methods of a class, like this: myBubble.paint(gBuffer). You can also access variables of the objects directly: myBubble.x - but that is not recommended, to avoid accidentally changing data in your object. You would also have to declare them public to allow access from outside the class. Try to use only methods, to access variables of an object and make your variables private (only accessable from within the class, set by default). Instead of calling OtherClass.a=10; you can define a public method in that class:

public void setA(int a)
{
    this.a=a;
}
this.a means: a reference to this instance, to this object of a class. You could also write, for instance:
public void setA(int varA)
{
    a=varA;
}

This way you are able to change data of an object indirectly, without dealing with the data itself. To get the value of a variable indirectly, you can use another method:

public int getA()
{
    return a;
}
, instead of calling: a=OtherClass.a;, a being a public int of the other class. In simple programs it is not neccessary to do this, but in big programs with many classes it provides for more safety and avoids bugs, by implementing the paradigma of encapsulation, which means - classes only interact with predefined interfaces (or methods) and are not allowed to change each others data directly.

//Sourcecode

import java.awt.*;
import java.applet.*;

//bubbles applet with a separate bubble class!

class Bubble
{
    //instance variables
    int x, y;
    Graphics g;

    //constructor
    public Bubble(int x, int y)
    {
        this.x=x;
        this.y=y;
    }

    public void drawRandomBubble(int x, int y)
    {
        int red=(int)(Math.random()*255);
        int green=(int)(Math.random()*255);
        int blue=(int)(Math.random()*255);

        Color randomColor=new Color(red, green, blue);
        g.setColor(randomColor);

        //generate a random number between 10 and 100
        int diameter=(int)(Math.random()*90)+10;

        //make mouse cursor the center of our random bubble
        g.fillOval(x-diameter/2,y-diameter/2,diameter,diameter);
    }


    public void paint(Graphics gr)
    {
        g=gr;
        drawRandomBubble(x, y);
    }
}

public class Project23 extends Applet
{
    Image Buffer;
    Graphics gBuffer;
    Bubble myBubble;

    public void init()
    {
        Buffer=createImage(size().width,size().height);
        gBuffer=Buffer.getGraphics();
    }

    public boolean mouseDown(Event evt,int x,int y)
    {
        myBubble = new Bubble(x,y);

        myBubble.paint(gBuffer);

        repaint();

        return true;
    }

    public void update(Graphics g)
    {
        paint(g);
    }

    public void paint(Graphics g)
    {
        gBuffer.setColor(Color.black);
        gBuffer.drawString("Click the applet to paint classy bubbles!", 30,20);
        g.drawImage (Buffer,0,0, this);
    }
}

You might wonder why you should need a separate class at all for the last program we discussed, but the advantages might come clearer to you in a more complicated one. The next applet uses a thread to make the bubbles you produce by clicking grow. The applet calles the grow() method of the GrowingBubbles class from within the run() method, which does all there is to do to make the bubbles grow: increment its diameter. Making the objects of your programs also objects of a separate class, allows for more logical and simple programming, especially for big projects, as you will soon discover.

//Sourcecode

import java.awt.*;
import java.applet.*;

class GrowingBubble
{
    //instance variables
    int x, y, diameter, startDiameter, endDiameter;
    Color randomColor;
    Graphics g;

    //constructor
    public GrowingBubble()
    {
        int red=(int)(Math.random()*255);
        int green=(int)(Math.random()*255);
        int blue=(int)(Math.random()*255);

        //each bubble object has one random color
        randomColor=new Color(red, green, blue);

        //start diameter between 10 and 30
        startDiameter=(int)(Math.random()*20)+10;

        //end diameter between 50 and 150
        endDiameter=(int)(Math.random()*100)+50;

        diameter=startDiameter;
    }

    public void setPosition(int x, int y)
    {
        this.x=x;
        this.y=y;
    }

    public void drawBubble()
    {
        g.setColor(randomColor);
        g.fillOval(x-diameter/2,y-diameter/2,diameter,diameter);
    }

    public void grow()
    {
        //quickly grow, till end diameter is reached
        if(diameter<endDiameter)
            diameter+=4;
    }

    public void paint(Graphics gr)
    {
        g=gr;
        drawBubble();
    }
}

public class Project24 extends Applet implements Runnable
{
    Image Buffer;
    Graphics gBuffer;
    GrowingBubble myBubble;
    Thread runner;
    boolean clicked;

    public void init()
    {
        Buffer=createImage(size().width,size().height);
        gBuffer=Buffer.getGraphics();
    }

    public void start()
    {
        if (runner == null)
        {
            runner = new Thread (this);
            runner.start();
        }
    }

    public void stop()
    {
        if (runner != null)
        {
            runner.stop();
            runner = null;
        }
    }

    public void run()
    {
        while(true)
        {
            //halt the thread for 15 ms here
            try {runner.sleep(15);}
            catch (Exception e) { }

            //bubble methods may only be accessed, if we have
            //created the object in the mouseDown method!
            if(clicked)
            {
                myBubble.grow();
                myBubble.paint(gBuffer);
            }

            repaint();
        }
    }

    public boolean mouseDown(Event evt,int x,int y)
    {
        myBubble = new GrowingBubble();

        myBubble.setPosition(x,y);

        clicked=true;

        return true;
    }

    public void update(Graphics g)
    {
        paint(g);
    }

    public void paint(Graphics g)
    {
        gBuffer.setColor(Color.black);
        gBuffer.drawString("Click the applet to paint growing bubbles!", 30,20);

        g.drawImage (Buffer,0,0, this);
    }
}

The bubbles you produce here don't just grow, they breathe! To achieve this, we need more than one object of our BreathingBubbles class, to make every one of them really independent from the others. To achieve this, we create an array of 100 bubble objects. With each mouseclick, a new one is created and initialized with the mouse coordinates. The object is responsible for it's own color, minimum diameter and maximum diameter.

//Sourcecode

import java.awt.*;
import java.applet.*;

class BreathingBubble
{
    //instance variables
    int x, y, diameter, startDiameter, endDiameter;
    boolean growing=true;
    Color randomColor;
    Graphics g;

    //constructor
    public BreathingBubble()
    {
        int red=(int)(Math.random()*255);
        int green=(int)(Math.random()*255);
        int blue=(int)(Math.random()*255);

        //each bubble object has one random color
        randomColor=new Color(red, green, blue);

        //start diameter between 10 and 30
        startDiameter=(int)(Math.random()*20)+10;

        //end diameter between 50 and 150
        endDiameter=(int)(Math.random()*100)+50;

        diameter=startDiameter;
    }

    public void setPosition(int x, int y)
    {
        this.x=x;
        this.y=y;
    }

    public void drawBubble()
    {
        g.setColor(randomColor);
        g.fillOval(x-diameter/2,y-diameter/2,diameter,diameter);
    }

    public void breathe()
    {
        //grow till end diameter is reached
        if(growing)
        {
            if(diameter<endDiameter)
                diameter++;
            else
                growing=false;
        }
        //shrink till start diameter is reached
        else
        {
            if(diameter>startDiameter)
                diameter--;
            else
                growing=true;
        }
    }

    public void paint(Graphics gr)
    {
        g=gr;
        drawBubble();
    }
}

public class Project25 extends Applet implements Runnable
{
    Image Buffer;
    Graphics gBuffer;
    BreathingBubble myBubble[];
    Thread runner;
    boolean clicked;
    int index;
    int MAX=100;

    public void init()
    {
        Buffer=createImage(size().width,size().height);
        gBuffer=Buffer.getGraphics();
        myBubble = new BreathingBubble[MAX];
    }

    public void start()
    {
        if (runner == null)
        {
            runner = new Thread (this);
            runner.start();
        }
    }

    public void stop()
    {
        if (runner != null)
        {
            runner.stop();
            runner = null;
        }
    }

    public void run()
    {
        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);

        while(true)
        {
            try {runner.sleep(15);}
            catch (Exception e) { }

            //bubble methods may only be accessed, if we have
            //created the object in the mouseDown method!
            if(clicked)
            {
                for(int i=0;i<index;i++)
                {
                    myBubble[i].breathe();
                    myBubble[i].paint(gBuffer);
                }
            }
            repaint();
        }
    }

    public boolean mouseDown(Event evt,int x,int y)
    {
        if(index<MAX)
        {
            myBubble[index] = new BreathingBubble();

            myBubble[index].setPosition(x,y);

            index++;
        }

        clicked=true;

        return true;
    }

    public void update(Graphics g)
    {
        paint(g);
    }

    public void paint(Graphics g)
    {
        gBuffer.setColor(Color.black);
        gBuffer.drawString("Click the applet to paint breathing bubbles!", 20,20);

        g.drawImage (Buffer,0,0, this);

        //paint the background white (must be done last!)
        gBuffer.setColor(Color.white);
        gBuffer.fillRect(0,0,size().width,size().height);
    }
}

back 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 next

0 - setup - getting your tools ready
1 - basic graphics functions
2 - simple methods and basic data types
3 - IF, ELSE and SWITCH: basic control structures
4 - introducing the operators
5 - methods with and without a return value
6 - using methods and basic mouse functions
7 - fonts, random numbers and timers
8 - flicker free graphics, GIF and JPEG display
9 - animation with GIF pictures, sprite animation
10 - loops, advanced color functions
11 - random colors and arrays
12 - digital clocks, HTML page parameters
13 - introducing classes and objects
14 - using the Vector class
15 - using mouseMove and mouseDrag
16 - keyboard commands and playing sound
17 - detecting collisions and intersections
18 - a Bouncing Balls applet
19 - fun with letters and words
20 - rotating lines and polygons
21 - sorting and shuffling


© 2000 by Johannes Wallroth
www.programming.de

watson@programming.de