Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- select * from chapters where contents = 'Thinking in Java 4e—Sample Chapters
- Bruce Eckel
- Permission to use, copy, modify, and distribute this
- computer source code (Source Code) and its documentation
- without fee and without a written agreement for the
- purposes set forth below is hereby granted, provided that
- the above copyright notice, this paragraph and the
- following five numbered paragraphs appear in all copies.
- 1. Permission is granted to compile the Source Code and to
- include the compiled code, in executable format only, in
- personal and commercial software programs.
- 2. Permission is granted to use the Source Code without
- modification in classroom situations, including in
- presentation materials, provided that the book "Thinking in
- Java" is cited as the origin.
- 3. Permission to incorporate the Source Code into printed
- media may be obtained by contacting:
- MindView, Inc. 5343 Valle Vista La Mesa, California 91941
- 4. The Source Code and documentation are copyrighted by
- MindView, Inc. The Source code is provided without express
- or implied warranty of any kind, including any implied
- warranty of merchantability, fitness for a particular
- purpose or non-infringement. MindView, Inc. does not
- warrant that the operation of any program that includes the Source Code
- will be uninterrupted or error-free. MindView,
- Inc. makes no representation about the suitability of the
- Source Code or of any software that includes the Source
- Code for any purpose. The entire risk as to the quality
- and performance of any program that includes the Source
- Code is with the user of the Source Code. The user
- understands that the Source Code was developed for research and
- instructional purposes and is advised not to rely
- exclusively for any reason on the Source Code or any
- program that includes the Source Code. Should the Source
- Code or any resulting software prove defective, the user
- assumes the cost of all necessary servicing, repair, or
- correction.
- 5. IN NO EVENT SHALL MINDVIEW, INC., OR ITS PUBLISHER BE
- LIABLE TO ANY PARTY UNDER ANY LEGAL THEORY FOR DIRECT,
- INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
- INCLUDING LOST PROFITS, BUSINESS INTERRUPTION, LOSS OF
- BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS, OR FOR
- PERSONAL INJURIES, ARISING OUT OF THE USE OF THIS SOURCE
- CODE AND ITS DOCUMENTATION, OR ARISING OUT OF THE INABILITY TO USE ANY
- RESULTING PROGRAM, EVEN IF MINDVIEW, INC., OR
- ITS PUBLISHER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- DAMAGE. MINDVIEW, INC. SPECIFICALLY DISCLAIMS ANY
- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE. THE SOURCE CODE AND DOCUMENTATION PROVIDED
- HEREUNDER IS ON AN "AS IS" BASIS, WITHOUT ANY ACCOMPANYING
- SERVICES FROM MINDVIEW, INC., AND MINDVIEW, INC. HAS NO
- Introduction
- 13
- OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
- ENHANCEMENTS, OR MODIFICATIONS.
- Please note that MindView, Inc. maintains a Web site which
- is the sole distribution point for electronic copies of the Source Code,
- http://www.MindView.net (and official mirror
- sites), where it is freely available under the terms stated above.
- If you think you\'ve found an error in the Source Code,
- please submit a correction using the feedback system that you will find at
- http://www.MindView.net.
- ///:~
- You may use the code in your projects and in the classroom (including your presentation
- materials) as long as the copyright notice that appears in each source file is retained.
- Coding standards
- In the text of this book, identifiers (methods, variables, and class names) are set in bold. Most
- keywords are also set in bold, except for those keywords that are used so much that the bolding
- can become tedious, such as “class.”
- I use a particular coding style for the examples in this book. As much as possible, this follows the
- style that Sun itself uses in virtually all of the code you will find at its site (see
- http://java.sun.com/docs/codeconv/index.html), and seems to be supported by most Java
- development environments. If you’ve read my other works, you’ll also notice that Sun’s coding
- style coincides with mine—this pleases me, although I had nothing (that I know of) to do with it.
- The subject of formatting style is good for hours of hot debate, so I’ll just say I’m not trying to
- dictate correct style via my examples; I have my own motivation for using the style that I do.
- Because Java is a free-form programming language, you can continue to use whatever style
- you’re comfortable with. One solution to the coding style issue is to use a tool like Jalopy
- (www.triemax.com), which assisted me in developing this book, to change formatting to that
- which suits you.
- The code files printed in the book are tested with an automated system, and should all work
- without compiler errors.
- This book focuses on and is tested with Java SE5/6. If you need to learn about earlier releases of
- the language that are not covered in this edition, the 1st through 3rd editions of the book are freely
- downloadable at www.MindView.net.
- Errors
- No matter how many tools a writer uses to detect errors, some always creep in and these often
- leap off the page for a fresh reader. If you discover anything you believe to be an error, please use
- the link you will find for this book at www.MindView.net to submit the error along with your
- suggested correction. Your help is appreciated.
- 14
- Thinking in Java 4e—Sample Chapters
- Bruce Eckel
- Introduction
- to Objects
- “We cut nature up, organize it into concepts, and ascribe significances as
- we do, largely because we are parties to an agreement that holds
- throughout our speech community and is codified in the patterns of our
- language ... we cannot talk at all except by subscribing to the
- organization and classification of data which the agreement decrees.”
- Benjamin Lee Whorf (1897-1941)
- The genesis of the computer revolution was in a machine. The genesis of our programming
- languages thus tends to look like that machine.
- But computers are not so much machines as they are mind amplification tools (“bicycles for the
- mind,” as Steve Jobs is fond of saying) and a different kind of expressive medium. As a result, the
- tools are beginning to look less like machines and more like parts of our minds, and also like
- other forms of expression such as writing, painting, sculpture, animation, and filmmaking.
- Object-oriented programming (OOP) is part of this movement toward using the computer as an
- expressive medium.
- This chapter will introduce you to the basic concepts of OOP, including an overview of
- development methods. This chapter, and this book, assumes that you have some programming
- experience, although not necessarily in C. If you think you need more preparation in
- programming before tackling this book, you should work through the Thinking in C multimedia
- seminar, downloadable from www.MindView.net.
- This chapter is background and supplementary material. Many people do not feel comfortable
- wading into object-oriented programming without understanding the big picture first. Thus,
- there are many concepts that are introduced here to give you a solid overview of OOP. However,
- other people may not get the big picture concepts until they’ve seen some of the mechanics first;
- these people may become bogged down and lost without some code to get their hands on. If
- you’re part of this latter group and are eager to get to the specifics of the language, feel free to
- jump past this chapter—skipping it at this point will not prevent you from writing programs or
- learning the language. However, you will want to come back here eventually to fill in your
- knowledge so you can understand why objects are important and how to design with them.
- The progress of abstraction
- All programming languages provide abstractions. It can be argued that the complexity of the
- problems you’re able to solve is directly related to the kind and quality of abstraction. By “kind” I
- mean, “What is it that you are abstracting?” Assembly language is a small abstraction of the
- underlying machine. Many so-called “imperative” languages that followed (such as FORTRAN,
- BASIC, and C) were abstractions of assembly language. These languages are big improvements
- over assembly language, but their primary abstraction still requires you to think in terms of the
- structure of the computer rather than the structure of the problem you are trying to solve. The
- programmer must establish the association between the machine model (in the “solution space,”
- 15
- which is the place where you’re implementing that solution, such as a computer) and the model
- of the problem that is actually being solved (in the “problem space,” which is the place where the
- problem exists, such as a business). The effort required to perform this mapping, and the fact
- that it is extrinsic to the programming language, produces programs that are difficult to write
- and expensive to maintain, and as a side effect created the entire “programming methods”
- industry.
- The alternative to modeling the machine is to model the problem you’re trying to solve. Early
- languages such as LISP and APL chose particular views of the world (“All problems are
- ultimately lists” or “All problems are algorithmic,” respectively). Prolog casts all problems into
- chains of decisions. Languages have been created for constraint-based programming and for
- programming exclusively by manipulating graphical symbols. (The latter proved to be too
- restrictive.) Each of these approaches may be a good solution to the particular class of problem
- they’re designed to solve, but when you step outside of that domain they become awkward.
- The object-oriented approach goes a step further by providing tools for the programmer to
- represent elements in the problem space. This representation is general enough that the
- programmer is not constrained to any particular type of problem. We refer to the elements in the
- problem space and their representations in the solution space as “objects.” (You will also need
- other objects that don’t have problem-space analogs.) The idea is that the program is allowed to
- adapt itself to the lingo of the problem by adding new types of objects, so when you read the code
- describing the solution, you’re reading words that also express the problem. This is a more
- flexible and powerful language abstraction than what we’ve had before.1 Thus, OOP allows you to
- describe the problem in terms of the problem, rather than in terms of the computer where the
- solution will run. There’s still a connection back to the computer: Each object looks quite a bit
- like a little computer—it has a state, and it has operations that you can ask it to perform.
- However, this doesn’t seem like such a bad analogy to objects in the real world—they all have
- characteristics and behaviors.
- Alan Kay summarized five basic characteristics of Smalltalk, the first successful object-oriented
- language and one of the languages upon which Java is based. These characteristics represent a
- pure approach to object-oriented programming:
- 1. Everything is an object. Think of an object as a fancy variable; it stores data, but
- you can “make requests” to that object, asking it to perform operations on itself. In
- theory, you can take any conceptual component in the problem you’re trying to solve
- (dogs, buildings, services, etc.) and represent it as an object in your program.
- 2. A program is a bunch of objects telling each other what to do by
- sending messages. To make a request of an object, you “send a message” to that
- object. More concretely, you can think of a message as a request to call a method that
- belongs to a particular object.
- 3. Each object has its own memory made up of other objects. Put
- another way, you create a new kind of object by making a package containing existing
- objects. Thus, you can build complexity into a program while hiding it behind the
- simplicity of objects.
- 1 Some language designers have decided that object-oriented programming by itself is not adequate to easily
- solve all programming problems, and advocate the combination of various approaches into multiparadigm
- programming languages. See Multiparadigm Programming in Leda by Timothy Budd (Addison-Wesley, 1995).
- 16
- Thinking in Java 4e—Sample Chapters
- Bruce Eckel
- 4. Every object has a type. Using the parlance, each object is an instance of a
- class, in which “class” is synonymous with “type.” The most important distinguishing
- characteristic of a class is “What messages can you send to it?”
- 5. All objects of a particular type can receive the same messages. This
- is actually a loaded statement, as you will see later. Because an object of type “circle” is
- also an object of type “shape,” a circle is guaranteed to accept shape messages. This
- means you can write code that talks to shapes and automatically handle anything that
- fits the description of a shape. This substitutability is one of the powerful concepts in
- OOP.
- Booch offers an even more succinct description of an object:
- An object has state, behavior and identity.
- This means that an object can have internal data (which gives it state), methods (to produce
- behavior), and each object can be uniquely distinguished from every other object—to put this in a
- concrete sense, each object has a unique address in memory.2
- An object has an interface
- Aristotle was probably the first to begin a careful study of the concept of type; he spoke of “the
- class of fishes and the class of birds.” The idea that all objects, while being unique, are also part
- of a class of objects that have characteristics and behaviors in common was used directly in the
- first object-oriented language, Simula-67, with its fundamental keyword class that introduces a
- new type into a program.
- Simula, as its name implies, was created for developing simulations such as the classic “bank
- teller problem.” In this, you have numerous tellers, customers, accounts, transactions, and units
- of money—a lot of “objects.” Objects that are identical except for their state during a program’s
- execution are grouped together into “classes of objects,” and that’s where the keyword class
- came from. Creating abstract data types (classes) is a fundamental concept in object-oriented
- programming. Abstract data types work almost exactly like built-in types: You can create
- variables of a type (called objects or instances in object-oriented parlance) and manipulate those
- variables (called sending messages or requests; you send a message and the object figures out
- what to do with it). The members (elements) of each class share some commonality: Every
- account has a balance, every teller can accept a deposit, etc. At the same time, each member has
- its own state: Each account has a different balance, each teller has a name. Thus, the tellers,
- customers, accounts, transactions, etc., can each be represented with a unique entity in the
- computer program. This entity is the object, and each object belongs to a particular class that
- defines its characteristics and behaviors.
- So, although what we really do in object-oriented programming is create new data types, virtually
- all object-oriented programming languages use the “class” keyword. When you see the word
- “type” think “class” and vice versa.3
- 2 This is actually a bit restrictive, since objects can conceivably exist in different machines and address spaces,
- and they can also be stored on disk. In these cases, the identity of the object must be determined by something
- other than memory address.
- 3 Some people make a distinction, stating that type determines the interface while class is a particular
- implementation of that interface.
- Introduction to Objects
- 17
- Since a class describes a set of objects that have identical characteristics (data elements) and
- behaviors (functionality), a class is really a data type because a floating point number, for
- example, also has a set of characteristics and behaviors. The difference is that a programmer
- defines a class to fit a problem rather than being forced to use an existing data type that was
- designed to represent a unit of storage in a machine. You extend the programming language by
- adding new data types specific to your needs. The programming system welcomes the new
- classes and gives them all the care and type checking that it gives to built-in types.
- The object-oriented approach is not limited to building simulations. Whether or not you agree
- that any program is a simulation of the system you’re designing, the use of OOP techniques can
- easily reduce a large set of problems to a simple solution.
- Once a class is established, you can make as many objects of that class as you like, and then
- manipulate those objects as if they are the elements that exist in the problem you are trying to
- solve. Indeed, one of the challenges of object-oriented programming is to create a one-to-one
- mapping between the elements in the problem space and objects in the solution space.
- But how do you get an object to do useful work for you? There needs to be a way to make a
- request of the object so that it will do something, such as complete a transaction, draw something
- on the screen, or turn on a switch. And each object can satisfy only certain requests. The requests
- you can make of an object are defined by its interface, and the type is what determines the
- interface. A simple example might be a representation of a light bulb:
- Type Name
- Interface
- Light
- on()
- off()
- brighten()
- dim()
- Light lt = new Light();
- lt.on();
- The interface determines the requests that you can make for a particular object. However, there
- must be code somewhere to satisfy that request. This, along with the hidden data, comprises the
- implementation. From a procedural programming standpoint, it’s not that complicated. A type
- has a method associated with each possible request, and when you make a particular request to
- an object, that method is called. This process is usually summarized by saying that you “send a
- message” (make a request) to an object, and the object figures out what to do with that message
- (it executes code).
- Here, the name of the type/class is Light, the name of this particular Light object is lt, and the
- requests that you can make of a Light object are to turn it on, turn it off, make it brighter, or
- make it dimmer. You create a Light object by defining a “reference” (lt) for that object and
- calling new to request a new object of that type. To send a message to the object, you state the
- name of the object and connect it to the message request with a period (dot). From the
- standpoint of the user of a predefined class, that’s pretty much all there is to programming with
- objects.
- The preceding diagram follows the format of the Unified Modeling Language (UML). Each class
- is represented by a box, with the type name in the top portion of the box, any data members that
- you care to describe in the middle portion of the box, and the methods (the functions that belong
- 18
- Thinking in Java 4e—Sample Chapters
- Bruce Eckel
- to this object, which receive any messages you send to that object) in the bottom portion of the
- box. Often, only the name of the class and the public methods are shown in UML design
- diagrams, so the middle portion is not shown, as in this case. If you’re interested only in the class
- name, then the bottom portion doesn’t need to be shown, either.
- An object provides services
- While you’re trying to develop or understand a program design, one of the best ways to think
- about objects is as “service providers.” Your program itself will provide services to the user, and it
- will accomplish this by using the services offered by other objects. Your goal is to produce (or
- even better, locate in existing code libraries) a set of objects that provide the ideal services to
- solve your problem.
- A way to start doing this is to ask, “If I could magically pull them out of a hat, what objects would
- solve my problem right away?” For example, suppose you are creating a bookkeeping program.
- You might imagine some objects that contain pre-defined bookkeeping input screens, another set
- of objects that perform bookkeeping calculations, and an object that handles printing of checks
- and invoices on all different kinds of printers. Maybe some of these objects already exist, and for
- the ones that don’t, what would they look like? What services would those objects provide, and
- what objects would they need to fulfill their obligations? If you keep doing this, you will
- eventually reach a point where you can say either, “That object seems simple enough to sit down
- and write” or “I’m sure that object must exist already.” This is a reasonable way to decompose a
- problem into a set of objects.
- Thinking of an object as a service provider has an additional benefit: It helps to improve the
- cohesiveness of the object. High cohesion is a fundamental quality of software design: It means
- that the various aspects of a software component (such as an object, although this could also
- apply to a method or a library of objects) “fit together” well. One problem people have when
- designing objects is cramming too much functionality into one object. For example, in your check
- printing module, you may decide you need an object that knows all about formatting and
- printing. You’ll probably discover that this is too much for one object, and that what you need is
- three or more objects. One object might be a catalog of all the possible check layouts, which can
- be queried for information about how to print a check. One object or set of objects can be a
- generic printing interface that knows all about different kinds of printers (but nothing about
- bookkeeping—this one is a candidate for buying rather than writing yourself). And a third object
- could use the services of the other two to accomplish the task. Thus, each object has a cohesive
- set of services it offers. In a good object-oriented design, each object does one thing well, but
- doesn’t try to do too much. This not only allows the discovery of objects that might be purchased
- (the printer interface object), but it also produces new objects that might be reused somewhere
- else (the catalog of check layouts).
- Treating objects as service providers is a great simplifying tool. This is useful not only during the
- design process, but also when someone else is trying to understand your code or reuse an object.
- If they can see the value of the object based on what service it provides, it makes it much easier to
- fit it into the design.
- The hidden implementation
- It is helpful to break up the playing field into class creators (those who create new data types)
- and client programmers4 (the class consumers who use the data types in their applications). The
- 4 I’m indebted to my friend Scott Meyers for this term.
- Introduction to Objects
- 19
- goal of the client programmer is to collect a toolbox full of classes to use for rapid application
- development. The goal of the class creator is to build a class that exposes only what’s necessary to
- the client programmer and keeps everything else hidden. Why? Because if it’s hidden, the client
- programmer can’t access it, which means that the class creator can change the hidden portion at
- will without worrying about the impact on anyone else. The hidden portion usually represents
- the tender insides of an object that could easily be corrupted by a careless or uninformed client
- programmer, so hiding the implementation reduces program bugs.
- In any relationship it’s important to have boundaries that are respected by all parties involved.
- When you create a library, you establish a relationship with the client programmer, who is also a
- programmer, but one who is putting together an application by using your library, possibly to
- build a bigger library. If all the members of a class are available to everyone, then the client
- programmer can do anything with that class and there’s no way to enforce rules. Even though
- you might really prefer that the client programmer not directly manipulate some of the members
- of your class, without access control there’s no way to prevent it. Everything’s naked to the world.
- So the first reason for access control is to keep client programmers’ hands off portions they
- shouldn’t touch—parts that are necessary for the internal operation of the data type but not part
- of the interface that users need in order to solve their particular problems. This is actually a
- service to client programmers because they can easily see what’s important to them and what
- they can ignore.
- The second reason for access control is to allow the library designer to change the internal
- workings of the class without worrying about how it will affect the client programmer. For
- example, you might implement a particular class in a simple fashion to ease development, and
- then later discover that you need to rewrite it in order to make it run faster. If the interface and
- implementation are clearly separated and protected, you can accomplish this easily.
- Java uses three explicit keywords to set the boundaries in a class: public, private, and
- protected. These access specifiers determine who can use the definitions that follow. public
- means the following element is available to everyone. The private keyword, on the other hand,
- means that no one can access that element except you, the creator of the type, inside methods of
- that type. private is a brick wall between you and the client programmer. Someone who tries to
- access a private member will get a compile-time error. The protected keyword acts like
- private, with the exception that an inheriting class has access to protected members, but not
- private members. Inheritance will be introduced shortly.
- Java also has a “default” access, which comes into play if you don’t use one of the aforementioned
- specifiers. This is usually called package access because classes can access the members of other
- classes in the same package (library component), but outside of the package those same
- members appear to be private.
- Reusing the implementation
- Once a class has been created and tested, it should (ideally) represent a useful unit of code. It
- turns out that this reusability is not nearly so easy to achieve as many would hope; it takes
- experience and insight to produce a reusable object design. But once you have such a design, it
- begs to be reused. Code reuse is one of the greatest advantages that object-oriented programming
- languages provide.
- The simplest way to reuse a class is to just use an object of that class directly, but you can also
- place an object of that class inside a new class. We call this “creating a member object.” Your new
- class can be made up of any number and type of other objects, in any combination that you need
- 20
- Thinking in Java 4e—Sample Chapters
- Bruce Eckel
- to achieve the functionality desired in your new class. Because you are composing a new class
- from existing classes, this concept is called composition (if the composition happens
- dynamically, it’s usually called aggregation). Composition is often referred to as a “has-a”
- relationship, as in “A car has an engine.”
- Car
- Engine
- (This UML diagram indicates composition with the filled diamond, which states there is one car.
- I will typically use a simpler form: just a line, without the diamond, to indicate an association.5)
- Composition comes with a great deal of flexibility. The member objects of your new class are
- typically private, making them inaccessible to the client programmers who are using the class.
- This allows you to change those members without disturbing existing client code. You can also
- change the member objects at run time, to dynamically change the behavior of your program.
- Inheritance, which is described next, does not have this flexibility since the compiler must place
- compile-time restrictions on classes created with inheritance.
- Because inheritance is so important in object-oriented programming, it is often highly
- emphasized, and the new programmer can get the idea that inheritance should be used
- everywhere. This can result in awkward and overly complicated designs. Instead, you should first
- look to composition when creating new classes, since it is simpler and more flexible. If you take
- this approach, your designs will be cleaner. Once you’ve had some experience, it will be
- reasonably obvious when you need inheritance.
- Inheritance
- By itself, the idea of an object is a convenient tool. It allows you to package data and functionality
- together by concept, so you can represent an appropriate problem-space idea rather than being
- forced to use the idioms of the underlying machine. These concepts are expressed as
- fundamental units in the programming language by using the class keyword.
- It seems a pity, however, to go to all the trouble to create a class and then be forced to create a
- brand new one that might have similar functionality. It’s nicer if we can take the existing class,
- clone it, and then make additions and modifications to the clone. This is effectively what you get
- with inheritance, with the exception that if the original class (called the base class or superclass
- or parent class) is changed, the modified “clone” (called the derived class or inherited class or
- subclass or child class) also reflects those changes.
- Base
- Derived
- 5 This is usually enough detail for most diagrams, and you don’t need to get specific about whether you’re using
- aggregation or composition.
- Introduction to Objects
- 21
- (The arrow in this UML diagram points from the derived class to the base class. As you will see,
- there is commonly more than one derived class.)
- A type does more than describe the constraints on a set of objects; it also has a relationship with
- other types. Two types can have characteristics and behaviors in common, but one type may
- contain more characteristics than another and may also handle more messages (or handle them
- differently). Inheritance expresses this similarity between types by using the concept of base
- types and derived types. A base type contains all of the characteristics and behaviors that are
- shared among the types derived from it. You create a base type to represent the core of your ideas
- about some objects in your system. From the base type, you derive other types to express the
- different ways that this core can be realized.
- For example, a trash-recycling machine sorts pieces of trash. The base type is “trash,” and each
- piece of trash has a weight, a value, and so on, and can be shredded, melted, or decomposed.
- From this, more specific types of trash are derived that may have additional characteristics (a
- bottle has a color) or behaviors (an aluminum can may be crushed, a steel can is magnetic). In
- addition, some behaviors may be different (the value of paper depends on its type and condition).
- Using inheritance, you can build a type hierarchy that expresses the problem you’re trying to
- solve in terms of its types.
- A second example is the classic “shape” example, perhaps used in a computer-aided design
- system or game simulation. The base type is “shape,” and each shape has a size, a color, a
- position, and so on. Each shape can be drawn, erased, moved, colored, etc. From this, specific
- types of shapes are derived (inherited)—circle, square, triangle, and so on—each of which may
- have additional characteristics and behaviors. Certain shapes can be flipped, for example. Some
- behaviors may be different, such as when you want to calculate the area of a shape. The type
- hierarchy embodies both the similarities and differences between the shapes.
- Shape
- draw()
- erase()
- move()
- getColor()
- setColor()
- Circle
- Square
- Triangle
- Casting the solution in the same terms as the problem is very useful because you don’t need a lot
- of intermediate models to get from a description of the problem to a description of the solution.
- With objects, the type hierarchy is the primary model, so you go directly from the description of
- the system in the real world to the description of the system in code. Indeed, one of the
- difficulties people have with object-oriented design is that it’s too simple to get from the
- beginning to the end. A mind trained to look for complex solutions can initially be stumped by
- this simplicity.
- 22';
Advertisement
Add Comment
Please, Sign In to add comment