Nava
Nava
Nava
pontos:
a) Permitir registo de cartões, sem repetir o número na mesma operadora; (2,0v)
b) Permitir a remoção de um determinado cartão registado; (1,0v)
c) Recarregar em um determinado número (incluir megas caso seja operadora Abc);
(1,5v)
d) Transferir saldo para outro número da mesma operadora; (2,0v)
e) Txunar (Emprestar s might resemble:
class Employee {
String name;
...
}
Typically, Java classes are defined one per .java file so Employee would be in
Employee.java and compiled to Employee.class. When a class references
another class, the Java compiler finds the associated class definition to perform
type checking and so on. For example, Employee references String, which the
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model -1
Java Object Model
compiler finds in file String.class stored in the standard Java class library.
Variable Definitions
Variable definitions are of the form:
modifiers TypeName name;
where modifiers include access specifiers (discussed in a section below) and
static if the variable is a class variable.
You may also initialize Java variables to any constant or nonconstant object
(except forward references to members, because they will not yet have been
initialized):
// Java code
class T {
int i = 0; // instance variable initialization
static int version = 3; // class variable init
String id = "x432"; // initialize object variable
}
The Java language has a static block initializer for initializing such things as
static
arrays or for determining initialization values that cannot be calculated until
runtime:
class TT {
static int[] a = new int[100];
static {
// init all elements to 2
for (int i=0; i<100; i++) a[i]=2;
}
}
Static variables are initialized and static initializers are executed exactly
once-upon class
loading.
Method Definitions
In Java, methods must be defined within the class definition. The general syntax
for methods is:
modifiers ReturnTypeName methodName(argument-list) {
body
}
where ReturnTypeName can be a primitive type, a class, or an array. The
modifiers include access specifiers (discussed in a section below) and static if
Java Object Model -2
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model
the method is a class method. For example, to return an array of strings, the
syntax is:
String[] foo() {...}
All methods must specify a return type, even if it is void (indicating no return
value).
Some of the most common methods are so-called getter/setter accessor methods
that provide controlled access to the state of an object. For example, consider the
following simple employee record definition:
class Employee {
String name = null;
void setName(String n) {
name = n;
}
String getName() {
return name;
}
}
The Java language has no special ordering requirements for method definitions. For
example, method setName could call getName as far as Java is concerned as in:
void setName(String n) {
String old = getName();
if ( !old.equals(n) ) { // same?
name = n; // only set if different
}
}
Java also allows you to reuse method names (called method overloading). You
may reuse any method name in the same class as long as each formal argument list
is different. For example,
class Employee {
void giveBonus(StockOptions opt) {...}
void giveBonus(float cash) {...}
}
Constructors
The Employee class definition above initializes the name instance variable to null
so that references such as
Employee e = new Employee();
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model -3
Java Object Model
start out without a useful value for name--you must call method setName
explicitly. How do you set the value of name during object construction by
passing in a value? By specifying a constructor with an argument.
Java constructors are methods that have the same name as the enclosing class and
no return type specifier. In general they also are public, which we will discuss
later. The formal argument list of the constructor must match the actual argument
list used in any new expression. To be able to execute:
Employee e = new Employee("Jim");
you must specify a constructor in Employee:
class Employee {
String name = null;
public Employee(String n) {
name = n;
}
...
}
You can overload constructors just like regular methods. For example, extending
the Employee definition to include salary information might induce you to create a
constructor to set both instance variables:
class Employee {
String name = null;
float salary = 0.0;
public Employee(String n) {
name = n;
}
public Employee(String n, float sal) {
name = n;
salary = sal;
}
...
}
If you specify a constructor with arguments it is a good idea to specify a default
(sometimes called copy) constructor--a constructor with no arguments (one is
created for you automatically if you do not specify one). Using expression "new
Employee()" calls the default constructor:
class Employee {
public Employee() {
name = "a useful default name";
}
Java Object Model -4
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model
...
}
Class Inheritance
Java supports the single inheritance model, which means that a new Java class can
be designed that incorporates, or inherits, state variables and functionality from
one existing class. The existing class is called the superclass and the new class is
called the subclass. Specify inheritance with the extends keyword. For example,
to define a manager as it differs from an employee:
you would write the following:
class Manager extends Employee {
...
}
All classes without explicit superclasses are considered direct subclasses of class
Object. Therefore, all classes directly or indirectly inherit from Object.
The Manager subclass inherits all of the state and behavior of the Employee
superclass (except for private members of Employee as we describe later).
Subclasses may also add data or method members:
class Manager extends Employee {
int parkingSpot;
void giveRaiseTo(Employee e) {...}
}
To illustrate what a Manager object would look like in memory, consider the
following Employee definition:
class Employee {
String name = null;
public Employee(String n) {
name = n;
}
}
A Manager object contains both a name which it inherits from Employee and a
parking spot:
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model -5
Java Object Model
Subclasses may override methods defined in the superclass by simply redefining
them. For example, to redefine the getName method in Manager, you could do the
following:
class Manager {
...
String getName() {
return "manager " + name;
}
}
The behavior of a Manager would now be different than a generic Employee with
respect to getName.
Object Type Equivalence
Recall that class inheritance is an identity relationship in that a subclass is a
specialization of the superclass. You can say that a manager is an employee. In
Java, this implies that an Employee reference can refer to any kind/specialization
of Employee:
Employee m = new Manager();
The reverse is not true, however. It is not the case that an employee is a manager.
The compiler will produce an error message if you type in the following:
// can't convert Employee to Manager!
Manager m = new Employee();
If you use a cast to fool the compiler, the Java virtual machine will cause an
exception at runtime. You cannot make Java do something that is not "type safe":
// will generate runtime ClassCastException
Manager m = (Manager) new Employee();
The flexibility of object-oriented code relies on the type equivalence or "automatic
conversion" of references to subclasses. Methods will very commonly define
generic formal argument types, but callers will pass specific subclasses as actual
arguments. For example, the following method accepts any kind of Employee:
class Company {
void promote(Employee e) {...}
...
}
The callers of method promote can pass an Employee object, a Manager object, or
any other object whose type is a subclass of Employee. The compiler compares
Java Object Model -6
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model
actual to formal arguments in the light of type equivalence just like the assignment
shown above. Hence, passing a Dog object, for example, would make the compiler
generate an error message about the non-equivalence.
Scope Override Keywords
Inheritance introduces several scoping issues related to member variables and
methods. In one of the above examples, Manager overrode Employee's getName
method to change its behavior. What if you wanted to refine the behavior instead
of replace it totally? You cannot simply call getName as you are already in
getName (an infinite recursion loop would occur). The question more precisely
then is how can you access the getName method in the super class. Prefix the
method call with "super.", which informs the compiler you would like the
inherited version of getName not the getName defined in the current class. For
example,
class Manager {
...
String getName() {
return "manager " + super.getName();
}
}
The getName method in this class now tacks on the string manager to whatever
the superclass defined getName to return.
What if you define a variable member with the same name as a variable inherited
from the superclass? How can you access both of them? Use this.variable to
access the variable in the current class and super.variable to access the variable
inherited from the superclass.
A more common variation of this problem arises when you define the argument of
a method to have the same name as a member variable. Again, the this keyword
provides a scope override to allow unambiguous references:
class Employee {
String name = null;
void setName(String name) {
// member var = argument
this.name = name;
}
}
Constructors and Inheritance
Constructors are not automatically inherited by subclasses. In other words, if
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model -7
Java Object Model
Manager does not specify a constructor, you cannot do the following:
Manager m = new Manager("John");
even if its superclass, Employee, defines a constructor with a String argument.
You could define a constructor in Manager that performs the appropriate
initialization, but what if you wanted to define the Manager constructor as a
refinement of the Employee constructor? Use the scope override keyword super
like a method call. For example,
class Employee {
String name = null;
public Employee(String n) {
name = n;
}
}
class Manager extends Employee {
int parkingSpot;
Manager(String n) {
super(n); // call constructor Employee(String)
parkingSpot = -1;
}
}
Note that any call to super() must be the first statement of the Java constructor.
A call to super() is inserted by default if one is not specified explicitly.
Also, the first statement may be a call to another constructor within the same
class with the help of the this keyword. Typically you will write a general
constructor and a bunch of small ones that refer to the general constructor. This
technique is one way to provide default values for constructor arguments. For
example, consider the following definition:
public class Circle {
float area = 0, radius = 0;
...
public Circle(float radius) {
this.radius = radius;
area = 3.14159 * radius * radius;
...
}
public Circle() {
this(2.0);
}
...
}
The first constructor performs certain "standard" initializations, as is common for
Java Object Model -8
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model
many classes. Note that the second constructor (the no-argument constructor)
contains a single line of code. In this context, this() represents an invocation of
another constructor, namely, a constructor whose parameter list matches the
invocation arguments. In this case, the invocation matches the first constructor
definition. With this functionality, it's easily to provide a variety of
constructors
with different signatures that indirectly establish default values for state
variables.
Order of Initialization and Constructor Calls
When an object of class T is instantiated, the following order of events is
observed:
1. An implied or explicit call to the superclass constructor of T is called, thereby
initializing its portion of the object.
2. The member variables of T are initialized in the order they are defined.
3. The remainder of the constructor for T is executed (the portion after an explicit
reference to the superclass constructor).
Using the Manager class above as an example, the order of initialization for:
Manager m = new Manager("Terence");
would be:
1. The constructor for class Manager is called.
2. The constructor Employee("Terence") is called.
3. The constructor for class Object (Employee's superclass) is called.
4. The member variables of Object are initialized.
5. The constructor for Object is executed.
6. The member variables of Employee are initialized.
7. The constructor for Employee is executed.
8. The member variables of Manager are initialized.
9. The constructor for Manager is executed.
Polymorphism (Late Binding)
Object-oriented code is flexible because the implementations of objects are
© 1996-2003 jGuru.com. All Rights Reserved.
ks.fhv.ljvcbqlb s;olcuvwc.kwv . kd,j xlqs,jc uqjcgdm n
ivfhkasc ,nzjbcsqvihfksc na,
X
}
...
}
class Developer extends Employee {
void goOnVacation() {
Java Object Model -10
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model
Y
}
...
}
To illustrate how the target object (the object receiving the message/method call)
type dictates which method implementation to execute, examine the following
code snippet:
Manager m = new Manager();
Developer d = new Developer();
Employee jim = m;
Employee frank = d;
jim.goOnVacation(); // executes X, this==jim
frank.goOnVacation(); // executes Y, this==frank
Variables jim and frank have type Employee as far as the compiler is concerned-you
could
be
referring
to
any
subclass
of
Employee.
It's
not
until
run-time,
when
the
exact
type
of
the
object
is
known
(that
is,
which
subclass).
The
exact
method
can then be
determined.
In summary, polymorphism refers to the multiple forms that an Employee can
take on (its subclasses) and late binding refers to the mechanism for achieving the
flexibility.
Access Rights to Class Members
Data hiding is an important feature of object-oriented programming that prevents
other programmers (or yourself) from accessing implementation details of a class.
In this way, data hiding limits or prevents "change propogation" that arises when
users of a class rely on its implementation rather than its interface.
The two most common class member access modifiers are public and private.
Any member modified with public implies that any method in any class may
access that member. Conversely, any member modified with private implies that
only methods of the current class may refer to that member (even subclasses are
denied access).
In general, it is up to the programmer to determine the appropriate level of
visibility, but there are a few reasonable guidelines:
• constructors are public so other classes can instantiate them. A class with only
private constructors cannot usually be instantiated (except via static
intializers/methods).
• data members should be private, forcing access through public getter/setter
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model -11
Java Object Model
methods like getName and setName from the Employee class above. The state of
an object is almost always part of the implementation, which you want to prevent
other programmers from relying upon.
While packages are discussed below, for completeness, we discuss the remaining
visibility levels. For the moment, consider packages to be logical collections of
classes such as the Java AWT package that groups the GUI widgets etc...
Any nonmodified member of a class is visible to any method of any class within
the same package, but no methods in classes outside the package may refer to
those members. For example, this makes sense that a Window class could access
the non-private members of the Button class if they belonged to the same
package.
A protected member of a class has the same visibility as a nonmodified member
except that all subclasses, even outside the package, may access it.
One final complication and our access picture is complete. Classes may also be
modified with public (or have no modifier). The public classes within a package
are visible to classes outside the package, but nonmodified classes are not. We
mention public classes versus members here because nonmodified, protected,
and public members are only visible (according to the rules we laid out above) if
the enclosing class is public. We explore this notion in more detail in the
packages section below.
To summarize, in order of least to most protective, here are the Java member
access specifiers:
• A public member is visible to any other class. Classes outside the package can
see the member only if its defining class is public.
• A protected member is visible to any class within the package and to any
subclass even if the subclass is defined in another package as long as the
superclass is public.
• A member without a specifier is considered "package friendly" and can be seen by
any class in the package.
• A private member is visible only within its defining class.
Another way to look at visibility within a single package is that a member of a
class is visible throughout the package when the member is public, protected,
or unmodified.
Java Object Model -12
© 1996-2003 jGuru.com. Al
It's easier to work in teams-you do not have to relink your entire project after you
(or someone else on your team) change a module.
Classes Are Conscious
Java classes are "conscious" in the sense that they know their type at runtime,
whereas C structs and Pascal records are blocks of "unconscious" data--a block
of memory. For example, if you call a function f on some data for which it was
not designed to operate, something unexpected will happen at best or it will crash
the program. In java, calling a method of a class that has been modified to no
longer implement f, results in the runtime exception NoSuchMethodException.
The class of an object can be determined at runtime via the instanceof operator,
which returns a boolean value, for example,
boolean isButton(Object o) {
return (o instanceof Button);
}
The Relationship between C Structures and Java
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model -21
Java Object Model
Classes
[This section is intended as review for C++ programmers and as a bridge from C
to Java for C programmers.]
Consider how you would build a list manager for arbitrary elements in C. First,
you would define operations on a list such as add and get:
void list_add(void *item) {..}
void *list_get(int i) {..}
Second, you might choose the implementation data structure such as an array of
"void *":
static void *data[MAX_ELEMENTS];
static int nelements = 0;
To ensure that users of the list manager do not access the data structure explicitly
(isolating implementation from interface), we have made the data static, thus
making it invisible outside of the file.
Naturally, the problem with this scheme is that only one list manager can be
created. To solve this, you would put the data within a struct and then list
manager users would each allocate one of the structs:
struct List {
void *data[MAX_ELEMENTS];
int nelements;
};
void list_add(struct List *list, void *item) {..}
void *list_get(struct List *list, int i) {..}
void list_init(struct List *) {nelements=0;}
Notice that now each list function receives the particular list to operate on as the
first argument. Also note that an explicit initialization function is required to
initially set the fields of a List structure.
Unfortunately, this struct-based scheme opens up all of the data elements to the
users as they must see the definition of struct List to be able to use it.
A Java Implementation
A similar, but simpler and safer, solution to the struct-based scheme, is available
to Java programmers: Change the name struct to class. Place the functions
within the class definition. Finally, remove the first argument that indicates which
Java Object Model -22
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model
list to manipulate.
class List {
private Object data[];
private int nelements=0;
public void add(Object item) {..}
public Object get(int i) {..}
public List() {
data = new Object[MAX_ELEMENTS];
}
}
Notice that we have also changed:
• void * to Object, which refers to any Java object. (But cannot refer to a variable
of a primitive type.)
• list_add() to add() because moving it inside the class definition for List means
that it is now really List.add()! Function names are more general in Java.
• list_init() to List(), which is called the constructor for class List. Because
Java cannot allocate any space with a simple field (member) definition, we use the
constructor to allocate the space. We can, however, initialize nelements with the
definition.
• access specifiers have been added to prevent access to List's private data.
Using the List Managers
Now compare how you would use the C list manager versus the Java list manager:
/* C code */
#include "List.h"
foo() {
struct List *mylist = (struct List *)
calloc(1, sizeof(struct List));
list_add(mylist, "element 1");
list_add(mylist, "element 2");
/* we can write to mylist->data[] directly! */
}
In Java, you would write:
// Java code
void foo() {
List mylist = new List();
mylist.add("element 1");
mylist.add("element 2");
// cannot write to mylist.data[] directly!
}
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model -23
Java Object Model
The crucial difference between C and Java is in the function call versus method
invocation; i.e.,
list_add(mylist, "element 1");
versus
mylist.add("element 1");
In C you write function-centric code. In Java, you write data-centric code. That is,
"execute this code using this data" versus "here's some data...operate on it".
Object-oriented programmers typically go further than this to say "ask the list to
add "element 1" to itself." Another common terminology (from Smalltalk) would
describe this operation as "send the message add to the object mylist with an
argument of "element 1"."
Are Classes Only For Object-Oriented Programming?
The Java version of the list manager described above can be viewed merely as a
simpler description than the C version. In fact, classes that are not derived from
another class (using inheritance) are really nothing more than fancy struct
definitions. All the mumbo-jumbo surrounding object-oriented programming such
as polymorphism can be ignored while studying the benefits of encapsulation and
data hiding:
• encapsulation: the methods that operate on an object are packaged up with that
object.
• data hiding: portions of the object's data may be hidden from the user, thus,
allowing the implementation of that object to be isolated from the user. Changes to
the implementation would not affect a user's code as all access to the data element
can be controlled through a set of functions.
[MML: 0.995a]
[Version: $Id: //depot/main/src/edu/modules/JavaObjectModel/javaObjectModel.mml#2 $]
Java Object Model -24
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model
© 1996-2003 jGuru.com. All Rights Reserved.
Java Object Model -25