1. Trang chủ
  2. » Công Nghệ Thông Tin

Que using java 2 special edition standard edition dec 2000 ISBN 0789724685

588 54 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 588
Dung lượng 2,86 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

A class defines an abstraction using a set of attributes and behavior that represents what is common among objects in a group.. Note To distinguish class variables with variables that ar

Trang 1

Most control flow expressions in Java direct program executionbased on a computed true or false value For instance, asyou'll see later in this chapter, an if (expression) statementcauses the next statement to be executed only if expressionevaluates to true. You can actually write something like if (true), but this is not very useful in general (except for

typically evaluate to the true and false literals

associated with the boolean primitive type and not

to an object reference Boolean and boolean are

Table 6.1 Operations on Boolean Expressions

Trang 2

= Assignment As in lightOn = true;.

== Equality This produces a true if the two

equivalent to EXCLUSIVE OR (XOR)

operands are true For non-boolean

operands, it is interpreted as a bitwiseoperator

| OR Produces a false if and only if both

operands are false For non-boolean

operands, it is interpreted as a bitwiseoperator

^ XOR Produces true only if exactly one

(EXCLUSIVE OR) operand is true Fornon-boolean operands, it is interpreted

Trang 3

The most intuitive comparative operators are those that fall into

a category known as relational operators Relational operatorsinclude the standard greater-than and less-than symbols youlearned about back in third grade Conveniently enough, theywork the same in Java as they did back in third grade, too Forinstance, you know that if you write (3>4), you have writtensomething wrong (a false statement) On the other hand, (3<4)

is correct (a true statement) These examples use literal values,which makes them easy to evaluate, but not very useful in aprogram because their result is known in advance, and it is

always the same Fortunately, in Java and other languages, youare not limited to comparing constants when you use relationaloperators; you are free to use variables, so the statement

(accountBalance > minimumBalance) is also a valid

relational expression that provides much more potential for use

in a flow control statement These expressions are built usingthe operators shown here:

Trang 4

non-boolean operands It might not be immediately obvious

what this implies, so consider the following (illegal) expression:

a < b < c

Using left-to-right associativity, the expression a < b is

evaluated first to produce a boolean value of either true or

false. This value would then have to be compared to c. What

does it mean to ask if true (or false) is less than some other

operand? Unlike some languages, a boolean in Java is not the

concatenate boolean values with a string using the + or +=

operator and the string true or false will be displayed in the

output

Listing 6.1 QuickTest.javaA Simple Lesson from the Third

Grade

Trang 6

operator (==) is used to distinguish equality comparisons fromassignments In Java then, you would write the expression as(3==3). This would be read as "three equals three" and wouldproduce a true result when evaluated Similarly, the expression(3==4) would evaluate to false.

evaluate the expression However, if the operands are objectreferences, the purpose of these operators is to determine ifboth operands refer to exactly the same object Consider thefollowing example:

string1 == string2

In this expression, string1 and string2 must refer to thesame stringnot to two different strings that happen to containthe same sequence of charactersfor the expression to evaluate

to true. Consider the lines shown in Listing 6.2

Trang 8

be compared with another boolean for equality, so a compilererror results here if lastRace is any other data type.

Trang 9

is some reason that you must use an expression likethe one just given, be sure to use comments to

explain how the expression operates and, if possible,why you have chosen to implement your algorithmthat way

Trang 10

Wrapping the Primitive Types in ClassesUsing the Standard Mathematical Functions

Trang 11

Building a UML Class DiagramTroubleshooting

Trang 12

Classes are the building blocks of an object-oriented system, soit's important to define them and talk about how they relate toobjects before you learn to declare and use them On one hand,objects are relatively easy to define because they surround you.Obviously, this book you're reading and the keyboard on whichyou type are both objects The concreteness of objects makesthe concept simple to graspobjects are specific things (persons,places, ideas, and so on if you want to be complete) Turning toclasses, however, you must trade this concrete view for the

abstract

In nearly every aspect of life, from simple conversation to

scientific research, people have found it easier to understandobjects and work with them after they have been put into

categories that make similarities and differences clear The

world is too complex otherwise Imagine Henry Ford trying toexplain his plans for the Model T when there was no such

abstraction as a "car" from which to start When an automakerintroduces a new model today, you might be anxious to seewhat it looks like but no one has to tell you what it does Whenabstractions are used to group objects, the key is to focus onwhat they have in common and ignore the ways in which theydiffer when those differences are unimportant in a given

context

So how does this relate to classes? A class defines an

abstraction using a set of attributes and behavior that

represents what is common among objects in a group From aprogramming standpoint, these attributes are variables thatrepresent state and you define methods to act on these

variables as a way to model behavior With proper adherence toencapsulation, these methods define everything that is allowed

in terms of accessing, using, and changing the state of an

object Any behavior that is important to the system you're

Trang 13

to state and behavior With this in mind, you decide you need aclass named StopLight. The first step is to define variables tohold the state of a StopLight. As an initial pass, you decidethat the color of the light is the only state of a StopLight thatthe rest of your system needs to know To represent this state,you select a single integer variable named greenYellowRedthat will hold the value of the light color Java offers a muchbetter way than using an integer here but you'll learn aboutthat a little later Given these design choices, here's an exampleclass declaration:

it is likely that you would have a method called

changeLight(), which would cause the light to change fromred to green (probably by changing the greenYellowRed

variable) The following modified declaration of StopLight

Trang 14

Note

To distinguish class variables with variables that areparts of methods, class variables are often referred

to as fields, or class scope variables In the previous

example, the greenYellowRed variable would be afield of the StopLight class

Trang 15

When dealing with classes, it's important to remember that

classes do not enable programmers to do anything more thanthey would be able to do without them Although it might besignificantly more work, you could write all OOP programs

structurally

Classes are used for the same reason large companies are

divided into departments and those departments are dividedinto subdepartments When a company is faced with organizinghundreds of people around hundreds of tasks, a divide and

conquer strategy is the only way to survive A departmentalarchitecture divides tasks into manageable, and hopefully

related, pieces that can be addressed by an appropriate group

of staff If you're in the engineering department, you care aboutgetting your paycheck on time, but you're probably not

concerned with how the payroll system knows how to handlepaid holidays If you're in the payroll department, however, youmight care a great deal As far as the rest of the company isconcerned, the processing of paychecks has been fully

encapsulated within the payroll department Taking this sameidea and moving it into the software arena is what OOP doeswhen responsibility is divided among classes As with a

company department, each class should be able to do one thingand do it well so the rest of the system can be assured that theassigned tasks are carried out

intricacies of that task and use the class and the methods itprovides Because the class mechanisms are hidden within its

Trang 16

Beyond encapsulation, classes allow you to change how youthink about the elements of your programs By writing classesthat enclose everything associated with particular tasks or

entities, you can build types that have meaning in the problemdomains in which you work You are not limited to describingyour program elements as integers, Booleans, or any other

native data type Instead of using these relatively indistinct

mechanisms and relying on unattached functions to interprettheir values appropriately, you can build software with classtypes that help describe the problem being solved In the

preceding payroll example, a procedural approach could be

implemented that maintains holidays as integer day and monthvalues that are compared against the dates in a pay period

whenever a paycheck amount is calculated However, think ofhow much more expressive a class-based approach could be.Using a Calendar class, holidays could be maintained as a

collection of Date objects To produce a paycheck, each dayduring a pay period could also be represented as a Date that isqueried for whether it's a weekend day or holiday relative to thecurrent Calendar. The processing that must be performeddoesn't change significantly between the two approaches, but asystem built on classes allows responsibility to be clearly

divided and produces entities that support the thought processrequired to solve the problem

Although encapsulation frees developers who use a class fromhaving to know the implementation details, it is also a powerfulmeans of preventing accidental corruption of the data Whenaccess to the data members of a class is managed through

methods, relationships between members can be maintained sothat invalid states do not occur

Encapsulation and the capability to create your own descriptive

Trang 17

is in its support for inheritance You'll learn more about the

mechanics of inheritance a little later, but for now think of it as

a way to pull common behavior out of multiple classes and

implement that behavior in a separate class so that it can beshared

As an example of inheritance, consider a program that managesthe accounts at a bank Assume the bank offers both checkingand savings accounts to its customers Viewing each type

separately, you could write independent code to support therequired functionality However, this is unnecessary effort and amaintenance headache waiting to happen given the commonfeatures checking and savings accounts share A better

approach is to factor out the common attributes and behaviorshared by the account types and define a class to representthem You can define a class called GeneralAccount for thispurpose with an account balance attribute and methods to

check the balance, make a deposit, and make a withdrawal Youwon't use this GeneralAccount class to represent an actualaccount object but you can use it to simplify the development ofCheckingAccount and SavingsAccount classes If checkingaccounts at this bank do not pay interest, you can inherit thefunctionality of GeneralAccount when declaring

structures in a software system

Note

When new classes inherit the properties of another

Trang 18

relate them Code that makes use of a polymorphic type makesmethod calls on a reference to the superclass and the behaviorthat results is determined by the particular subclass

application displays the drawing using a loop that checks eachfigure created by the user and calls a specific function that

knows how to draw that type of shape This approach worksreasonably well until the program users add a requirement that

a triangle must also be supported as a drawing tool A

programmer must then locate the drawing loop, and every

other place shapes are treated differently based on their type,and update the code to understand triangles This update is not

Trang 19

maintenance and reliability drawback that can get out of handquickly in a system with any true complexity With OOP,

encapsulation comes into play first as a better approach to thisprogram The functions for drawing different shape types should

be located in the code that defines each shape, namely withinCircleShape, RectangleShape, and TriangleShape

classes The drawing functionality should be implemented as adraw method that holds all the knowledge required to draw theassociated shape on the screen This is already an improvementbecause the behavior of each shape is now encapsulated withinthe definition of the shapes themselves This encapsulation

significantly reduces the number of places code must be

modified if the drawing requirements for a particular shape arelater changed

There's still more, however A drawback in our system so far isthat although the draw methods are encapsulated within

classes, the program still has to call a separate method for eachshape type when the screen needs to be displayed This is

unnecessary effort because the program does not care aboutthe shape types; it only wants them to be drawn correctly Thecapability for a shape to be drawn correctly is a common

behavior found in each of the shape classes (CircleShape, RectangleShape, and TriangleShape)

This is where polymorphism comes into play Instead of definingthree unrelated classes, you can factor out the common

behavior that, in this case, is the capability for a shape to drawitself The example becomes a true OOP implementation when aGenericShape class with a draw method is defined as a

superclass for each of the three shape classes A

GenericShape does not correspond to any real shape, so ithas no implementation for its draw method However, this classdoes serve a significant purpose by declaring that its subclassesmust support a draw method With this change, the programcan keep track of its shapes as GenericShape instances rather

Trang 20

than a collection of CircleShape, RectangleShape, andTriangleShape instances This works because the programdoesn't need to know the difference, provided that it can direct

a shape of any type to draw itself When it's time to draw thescreen, the draw method of each GenericShape can be calledand, through polymorphism, the draw method of the specificshape type is called

the CircleShape and RectangleShape classes

can be treated just like the GenericShape class in

Java, you cannot perform an operation such as

getRadius that is reserved for the CircleShape

class on an instance of the GenericShape class

Trang 21

As stated at the beginning of this chapter, classes are the

building block in an object-oriented language such as Java Infact, Java, unlike C++, goes so far as to make it impossible todefine any variables or methods outside a class Everything you

do in Java is based on designing and implementing classes

Trang 23

public GeneralAccount( String accountNum ) { accountNumber = accountNum;

}

public void makeWithdrawal( float amount ) { balance -= amount;

public class GeneralAccount

Declaring a class states several things, but probably the mostimportant one is the name of the class (GeneralAccount) Inthe case of any public class, the name of the class must alsomatch the name of the file that contains it In other words, thisclass must appear in the file GeneralAccount.java.

Trang 24

A bit farther down, you will see several comments As you

learned in "Comments" (Chapter 3, "Data Types and Other

Tokens" ), comments can exist anywhere in the file and are

ignored by the compiler, but they help you leave messages foryourself or other programmers Next, you will see several fieldsdeclared Each of these variables is accessible from any of themethods in the class When you change them in one method, allthe other methods will see the new value

Trang 25

In general, Java class declarations take the form

AccessSpecifier Modifiers class NewClass extends SuperclassName implements InterfaceName

Trang 26

classes are known as inner classes and are discussed later in

this chapter When declaring a top-level class, you can statethat the class has public access, which is what you have seen

in the examples so far, or you can omit the access specifier andaccept the default access restrictions

Public Classes

Using the public specifier in a class declaration makes the

class accessible to all other classes A public class can be used(for example, as a data type for a class variable or a type for amethod parameter) or extended by any class Here's an

Trang 27

programmer Packages provide a way to organize your code byplacing related classes together Access restrictions are lessstringent between classes within the same package because theintent is for these classes to work together as a cohesive unit.With that said, package access can be distinguished from publicaccess Whereas any class can use a public class, by omittingthe public modifier, you can declare a class for use only byclasses within the same package

Remember that although package is a keyword in Java, you donot use it (or any other access specifier) in a declaration for aclass with package access Here's an example declaration:

class PictureFrame

Note

Package access is also known as "default" or

"friendly" access "Default" access is an appropriate

an inheritance hierarchy Note that both modifiers cannot beused in a single class declaration The reason for this will beclear after the supported modifiers are defined

Trang 28

inheritance is supposed to be one of the appeals of object-oriented programming

It is important to remember that the object-oriented approacheffectively enables you to create alternate versions of a class(by creating children that inherit its properties and change itsomewhat) Consequently, if you create a class to serve as acomplete implementation of some particular function (for

example, a class that will handle network communications using

Trang 29

possibility and ensure consistency The final modifier givesyou a precise way to make your intent clear to other

programmers regarding the use of a class

In addition, the compiler can carry out a number of

performance optimizations on a final class that otherwise wouldnot be possible Polymorphism allows you to write flexible code,but the associated dynamic method calls degrade performancesomewhat If you write code that calls a method on a non-finalclass instance, the compiler must allow for the possibility thatthe instance encountered at runtime will actually be an instance

of a subclass This means that the method must be looked upwhen the code is executed rather than being known when theclass is compiled If, instead, you use a final class, the methodcall is fully defined during compilation because there is no

possibility of a subclass instance being used Of course, thefinal modifier should only be used when a class should have

no subclasses The performance advantage is a side effect only,but you should use this as incentive to consider whether yourclasses should allow subclasses when you are declaring them.Here's an example declaration for a final class:

Trang 30

must be extended before an instance can be created The

abstract modifier indicates that a class implementation is

incomplete and must be added to before it can represent anactual object A declaration for an abstract class takes the

following form:

abstract class PictureFrame

A class that you have completely written and compiled can beincomplete depending on how common behavior is isolated andreused in an inheritance hierarchy The superclass that containsthe common behavior in such a hierarchy often does not containenough behavior to represent a valid object For example,

consider a grammar-checking program that must support

multiple written languages You could proceed by defining anEnglishChecker, a FrenchChecker, and a

SpanishChecker class in which each defines the required

functionality for a given language Knowing that some of themethods you need are independent of the language, you define

a GrammarChecker class as a common superclass that

contains these methods rather than repeating them in each

class This alone does not produce an abstract class, becauseeven though GrammarChecker does not implement all you

checkPunctuation(), this method can be declared in

GrammarChecker without an implementation (that is, an

Trang 31

flexible design needed for this example This structure supports

independent functionality of the program If a programmer laterneeded to add a GermanChecker class, a perfect starting pointwould be to look at the list of abstract methods in

a clean separation of the language-dependent and language-GrammarChecker to gain an understanding of what behaviorhas to be provided to support a new language

Begin with a letter, an underscore (_), or a currency symbol($, £, and so on)

Contain only letters, digits, underscores, and currency

Trang 32

Not be the same as any Java keyword (such as void orint)

Also, it is accepted practice to capitalize the first letter in thename of a class and use mixed case instead of underscores toseparate words (for example, MyClassName)

Although only required for public classes, it is generally a goodpractice to name the file in which NewClass is defined

NewClass.java. Doing so helps the compiler find NewClass,even if NewClass has not been compiled yet

SuperclassesExtending Another Class

One of the most important aspects of OOP is the capability touse the methods and fields of a class you have already built.This can be done by declaring a member variable that is a

Trang 33

By extending a class, you gain all the functionality of a

superclass while providing yourself the opportunity to add newbehavior or even modify existing behavior If you declare asubclass without defining any fields or methods (and use thesame access specifier and modifier, if any), the new class willbehave identically to its superclass and only differ by its name.The subclass would not be very interesting but it would be avalid class, and it would have all the fields and methods

Trang 34

A common mistake in object-oriented programming is to overuse inheritance Although inheritance is a powerful feature, a class hierarchy can become rigid if inheritance is taken to the extreme A standard rule of thumb is to apply the "is- a" versus "has-a" test.

For example, a Ford is a car, so a class hierarchy that defines a Ford class as a subclass of a Car class makes sense This example strictly follows an "is-a" definition, because there is nothing that a Ford does that a generic Car does not do A Ford is a unique classification of Car that has its own implementation

of automotive behavior, but you don't need to add some new capability, such as floating on water, when you declare a Ford class.

Slightly different from an "is-a" justification for inheritance is the "is-like-a" test.

In this case, you make use of inheritance to declare a subclass that is similar enough to its superclass to share its interface, but it is also dissimilar in that it requires additional methods to represent its behavior completely This design is not as clean an approach because treating the subclass as its superclass doesn't allow you to exercise all its functionality, but it can be useful.

If two classes cannot be described as having an "is-a" or "is-like-a" relationship,

you should not inherit one from the other For example, a car has an engine, but

it isn't an engine, so Car should not be a subclass of an Engine class A

composition approach should be used here so that Car contains a reference to

an Engine and delegates all functionality related to powering the vehicle to that instance.

The appropriate use of inheritance in these simple examples is obvious, but this

is not always the case You should exercise caution when considering inheritance and more often stress composition and delegation in your class designs to make them more flexible and better able to adapt to new requirements during their lifecycles.

Trang 35

Obviously, variables are an integral part of programs and, thus,classes as well In Chapter 3, you examined the various types

of variables, but now you must also consider how they are

employed in your programs and the different roles they canassume

When creating variables, whether they are as simple as integers

or as complex as derived classes, you must consider how theywill be used, what code will require access to the variables, andwhat degree of protection you want to provide to these

variables

The capability to access a given variable is dependent on twothings: the access specifier used when creating the variable andthe location of the variable declaration within a class

See "Literals: Assigning Values,"

Trang 36

encapsulate your code into self- sufficient and more logical

chunks

Furthermore, because OOP encourages and facilitates the reuse

of code that you have written beforehand, careful assignment ofaccess restrictions to code you write now prevents you fromlater doing something that you shouldn't

(Keep in mind that preventing access to a field does not preventthe use of it.) For example, if you were creating a Circle

class, there would most likely be several fields that would keeptrack of the properties of the class, such as radius, area, bordercolor, and so onmany of which might be dependent on each

other Although it might seem logical to make the radius fieldpublic (accessible by all other classes), consider what wouldhappen if a few weeks later you decided to write the code

Trang 38

statement would change the radius, it would not affect the areafield (remember that the area of a circle is a function of theradius and is equal to times the radius squared) As a result,you would be supplying the paintBall() method with

incorrect information

Because the area field depends on the radius, it should beupdated whenever the radius is changed Your first thoughtmight be to ask why area is a field at all instead of just beingthe return value of an area() method that is computed based

on the radius when needed Using a field that is derived fromone or more other fields is a common approach when

addressing performance Assume, in this case, that

performance is critical when the area of the circle is needed.Calling a method that computes the area each time is extraoverhead if the radius has not changed since the last call

Declaring a field to hold the area offers a better solution whenthe radius and area fields are properly protected as shown in

Trang 39

from outside the class, the area field is updated accordingly

This way the area of the circle is always correctly represented

by the field and is never computed unnecessarily

Ngày đăng: 26/03/2019, 17:10