• Tidak ada hasil yang ditemukan

Apple a2 = new Apple();

...

void setupApples() {

a1.diameter = 3.0f; // Comple-time error ...

a2.diameter = 8.0f; // Comple-time error ...

} ...

}

If we still need to access diameter in some capacity, we would usually add public get Diameter() and setDiameter() methods to the Apple class:

public class Apple {

private float diameter = 1.0f;

...

public void setDiameter(float newDiameter) { diameter = newDiameter;

}

public float getDiameter() { return diameter;

} ...

}

Creating methods like this is a good design rule because it allows future flexibility in changing the type or behavior of the value. We’ll look more at packages, access modi‐

fiers, and how they affect the visibility of variables and methods later in this chapter.

We have declared the new float variable gravAccel as static. That means that it is associated with the class, not with an individual instance, and if we change its value (either directly or through any instance of Apple), the value changes for all Apple objects, as shown in Figure 5-3.

Figure 5-3. Static variables shared by all instances of a class

Static members can be accessed like instance members. Inside our Apple class, we can refer to gravAccel like any other variable:

class Apple { ...

float getWeight () {

return mass * gravAccel;

} ...

}

However, since static members exist in the class itself, independent of any instance, we can also access them directly through the class. If we want to toss apples on Mars, for example, we don’t need an Apple object like a1 or a2 to get or set the variable gravAccel. Instead, we can use the class to select the variable:

Apple.gravAccel = 3.7;

This changes the value of gravAccel as seen by all instances. We don’t have to man‐

ually set each instance of Apple to fall on Mars. Static variables are useful for any kind of data that is shared among classes at runtime. For instance, you can create methods to register your object instances so that they can communicate, or so that you can keep track of all of them. It’s also common to use static variables to define constant

values. In this case, we use the static modifier along with the final modifier. So, if we cared only about apples under the influence of the Earth’s gravitational pull, we might change Apple as follows:

class Apple { ...

static final float EARTH_ACCEL = 9.8f;

...

We have followed a common convention here and named our constant with capital letters and underscores (if the name has more than one word). The value of EARTH_ACCEL is a constant; it can be accessed through the class Apple or its instances, but its value can’t be changed at runtime.

It’s important to use the combination of static and final only for things that are really constant. The compiler is allowed to “inline” such values within classes that ref‐

erence them. This means that if you change a static final variable, you may have to recompile all code that uses that class (this is really the only case where you have to do that in Java). Static members are also useful for values needed in the construction of an instance itself. In our example, we might declare a number of static values to represent various sizes of Apple objects:

class Apple { ...

static int SMALL = 0, MEDIUM = 1, LARGE = 2;

...

We might then use these options in a method that sets the size of an Apple, or in a special constructor, as we’ll discuss shortly:

Apple typicalApple = new Apple();

typicalApple.setSize( Apple.MEDIUM );

Again, inside the Apple class, we can use static members directly by name, as well;

there’s no need for the Apple. prefix:

class Apple { ...

void resetEverything() { setSize ( MEDIUM );

...

} ...

}

Methods

So far, our example classes have been fairly simple. We keep a few bits of information around—apples have mass, fields have a couple of apples, etc. But we have also touched on the idea of making those classes do stuff. All of our various PrintAppleDe tails classes have a list of steps that get executed when we run the program, for example. As we noted briefly before, in Java, those steps are bundled into a method.

In the case of PrintAppleDetails, that is the main() method.

Everywhere you have steps to take or decisions to make, you need a method. In addi‐

tion to storing variables like the mass and diameter in our Apple class, we also added a few pieces of code that contained actions and logic. Methods are so fundamental to classes that we had to create a few (think back to the printDetails() method in Apple or the setupApples() method in Field) even before getting here to the formal discussion of them! Hopefully, the methods we have discussed so far have been straightforward enough to follow just from context. But methods can do much more than print out a few variables or calculate a distance. They can contain local variable declarations and other Java statements that are executed when the method is invoked.

Methods may return a value to the caller. They always specify a return type, which can be a primitive type, a reference type, or the type void, which indicates no returned value. Methods may take arguments, which are values supplied by the caller of the method.

Here’s a simple example:

class Bird { int xPos, yPos;

double fly ( int x, int y ) {

double distance = Math.sqrt( x*x + y*y );

flap( distance );

xPos = x;

yPos = y;

return distance;

} ...

}

In this example, the class Bird defines a method, fly(), that takes as arguments two integers: x and y. It returns a double type value as a result, using the return keyword.

Our method has a fixed number of arguments (two); however, methods can have variable-length argument lists, which allow the method to specify that it can take any number of arguments and sort them out itself at runtime.2

Dokumen terkait