Showing posts with label Thinking in Java. Show all posts
Showing posts with label Thinking in Java. Show all posts

Wednesday, December 10, 2008

Inner Classes

Q1:

When you create an inner class, an object of that inner class has a link to the enclosing object that made it, and so it can access the members of that enclosing object -- without any special qualifications. In addition, inner classes have access rights to all the elements in the enclosing class.

How to understand this paragraph?

Answer: The inner class secretly captures a reference to the particular object of the enclosing class that was responsible for creating it. Then, when you refer to a member of the enclosing class, that reference is used to select that member. Construction of the inner-class object requires the reference to the object of the enclosing class, and the compiler will complain if it cannot access that reference. Most of the time this occurs without any intervention on the part of the programmer.

Q2. Does an outer class have access to the private elements of its inner class?

Seems the answer is yes from the result of my little test code. But why?

Q3.
If you're defining an anonymous inner class and want to use an object that's defined outside the anonymous inner class, the compiler requires that the argument reference be final. If you forget, you'll get a compile-time error message. Why?

Tuesday, December 9, 2008

Interfaces

The fields in an interface are implicitly static and final. The fields, of course, are not part of the interface. The values are stored in the static storage area for that interface.

Factory Method design patter: instead of calling a constructor directly, you call a creation method on a factory object which produces an implementation of the interface -- this way, in theory, your code is completely isolated from the implementation of the interface, thus making it possible to transparently swap one implementation for another.

An appropriate guideline is to prefer classes to interfaces. Start with classes, and if it becomes clear that interfaces are necessary, then refactor. Interfaces are a great tool, but they can easily be overused.

Thursday, December 4, 2008

The Key Words: static & public & final

public: so they are usable outside the package;
static: to emphasize that there's only one
final : to say that it's a constant.

Note that final static primitives with constant initial values(that is, compile-time constants)

Choosing composition vs. inheritatnce

Both composition and inheritance allow you to place subobjects inside your new class(Composition explicitly does this- with inheritance it's implicit.) You might wonder about the difference between the two, and when to choose one over the other.

Composition is generally used when you want the features of an existing class inside your new class, but not it's interface. That is, you embed an object so that you can use it to implement features in your new class, but the user of your new class sees the interface you've defined for the new class rather than the interface from the embedded object. For this effect, you embed private objects of existing classes inside your new classes.

Sometimes it makes sense to allow the class user to directly access the composition of your new class; that is, to make the member objects public. The member objects use implementation hiding themselves, so this is a safe thing to do. When the user knows you're assembling a bunch of parts, it makes the interface easier to understand.

When you inherit, you take an existing class and make a special version of it. In general, this means that you're taking a general-purpose class and specializing it for a particular need.

The is-a relationship is expressed with inheritance, and the has-a relationship is expressed with composition.

In OOP, the most likely way that you'll create and use code is by simply packaging data and methods together into a class, and using object of that class. You'll also use existing classes to build new classes with composition. Less frequently, you'll use inheritance. So although inheritance gets a lot of emphasis while learning OOP, it doesn't mean that you should use it everywhere you possibly can. On the contrary, you should use it sparingly, only when it's clear that inheritance is useful. One of the clearest ways to determine whether you should use composition or inheritance is to ask whether you'll ever need to upcast from your new class to the base class. If you must upcast, then inheritance is necessary, but if you don't need to upcast, then you should look closely at whether you need inheritance. The Polymorphism chapter provides one of the most compelling reasons for upcasting, but if you remember to ask "Do I need to upcast?" you'll have a good tool for deciding between composition and inheritance.

Overloading and Overriding

Overloading is a one of the ways in which Java implements one of the key concepts of Object orientation, polymorphism.Overloaded methods are differentiated only on the number, type and order of parameters, not on the return type of the method.(That is in brief, different signatures, different implementation, for the method)


Overriding a method means that its entire functionality is being replaced. It is something done in a child class to a method defined in a parent class. To override a method a new method is defined in the child class with exactly the same signature as the one in the parent class.(That is in brief, same signatures but different implementation)

Java SE5 has added the @Override annotation, which is not a keyword but can be used as if it were. When you mean to override a method, you can choose to add this annotation and the compiler will produce an error message if you accidentally overload instead of overriding.

The @Override annotation will thus prevent you from accidentally overloading when you don't meant to.

Monday, December 1, 2008

Introduction to objects

I like the example of objects in the classic book of java: Thinking in Java.
----------------
Type Name:
| Light |
----------- ----
Interface:
| on(); |
| off(); |
| brighten(); |
| dim(); |
------------------

| Light lt = new Light();
| lt.on();

The interface determines the requests that you can make for a particular object. A type has a method associated with each possible request, and when you make a particular request to an object, that method is called.

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).

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. 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.