|
RHS |
Notes for week 35
Concerning inheritance remember that ”has a” is not the same as “is a”
Keyword this - “references this object” (the object that holds the this-statement)
public class MyClass {
int price;
int age;
int y;public MyClass() {
price = 7;
}
public MyClass(int x) {
this(); //call no-args constructor
age = x;
}public MyClass(int y, int age) {
this(age); //call other constructor
//(which itself calls no-args constructor)
this.y = y;
}
}
When a constructor calls another constructor it must be done as the very first statement
Keyword super - “reference to super-class”
class MyNewClass extends MyClass {
public MyNewClass(int x, int y) {
super(y); //call constructor in super-class
price = x;
}
}
Calling constructor in super-class must also be the very first statement
super.super … is not possible (super only goes up one level)
When extending a class everything, except the constructors, is inherited.
EVERYTHING!
Even private variables – but they are not accessible directly
(they are private). To access inherited private variables we need to go
through public or protected (see later) methods (setters or getters).
Inherited private methods are also not directly accessible (so be careful!)
If class definition doesn't extend another class an “ extends
Object” is always implicitly performed.
Thus all classes in Java – except
the class Object – extends
another class. Either implicit (class Object)
or explicit (extends SuperClassName).
The class Object is the “grandmother of all classes”
Everything
from class Object is thus inherited in every class – e.g.
boolean equals(Object obj), int
hashCode(), String toString() (plus some
more – look in the API-documentation).
Overload refers to the technique where two methods are
defined using the same return-type, same name but different signature (name
and parameter-list so only parameter-list differs) – the two
methods normally works differently
Ex.:
public int max(int x1, int x2) {
if (x1 > x2)
return x1;
else
return x2;
}public int max(int x1, int, x2, int x3) {
if ((x1 > x2) && (x1 > x3))
return x1;
else if (x2 > x3)
return x2;
else
return x3;
}
Useful when “the same job” can be done in various ways (usually
depending on the number of arguments available (e.g. more than one
constructor (all do the same job – creates an object – but the
way they work depends on the number of arguments), or methods like the example
above).
Often used – makes it possible to use same name for same job (contract)
even if the methods signatures are different
Override refers to the technique where a method is defined with same return type and signature as an inherited method. Most often used because the method in the sub-class has to take more things into account (e.g. the extension of the super-class). Often the inherited method (from the super-class) is reused in the overriding method (in the sub-class)
Ex.:
public class A {
private int price;public A(int p) {price = p;}
public int getPrice() {return price;}
public int getAmount() {return price;}
}public class b extends A {
private int tax;public B(int p, int t) {
super(p);
tax = t;
}//override:
public int getAmount() {return getPrice() + tax;}
}
To protect members (mostly variables) they are normally declared private (visibility – “to
what are the member visible”)
If we know that a sub-class will have
to refer to the values and want to avoid that they have to go through methods
(as discussed above) we can make this possible by declaring the visibility protected
A
protected member is visible to the class itself and to any
sub-class (but otherwise same visibility as private)
Shadowing (mentioned above): Avoid it – normally a sign of bad design!
Super versus sub - The word super implies that the super-class is "bigger" than
the sub-class.
It’s the other way around! "Super" merely
implies that the super-class is at a higher "level" in the inheritance-hierarchy.
Normally the sub-class has more members (it inherits everything from the
super-class and (normally) extends it with more members!
Assignments in a class-hierarchy
Assigning a sub-class
object to a reference of a super-class type is Ok (because the sub-class is-a super-class
type). But only methods (members) of the reference type is available (so
extended members are not available through the super-class reference).
When calling a method through the super-class reference it is the actual
method in the object that is activated (e.g. if it contains a overridden
method – e.g.
toString(). If it doesn't contain an overridden
method it is the inherited method that is activated ).
Assigning a super-class object to a reference of a sub-class type is not possible directly – the sub-class reference “would know members that don't exist in the (super-class) object”
Ex.:
Public class A {}
Public class B extends A {}…
A a1 = new A();
B b = a1; //is NOT possible.
//Reference b of type B cannot be assigned reference a1 as a1 is of type A
But if the super-class reference actually refers to a sub-class type object it should be possible to assign this to a sub-class type reference – we need to type-cast!
So:
A a1 = new B();
B b = (B) a1; //IS possible.
//Object is of correct type even if the reference to it (a1) is of super-class type
These rules also work with parameters. You can use a sub-class type as actual argument.
Ex.: (assume class A and B from above):
Public void aMethod (A param) {}
This method can be called using a sub-class object: aMethod(new B()) because this object is-a super-class type!
This strongly extends the flexibility of methods!!
Any method designed
for a super-class type object works perfectly with any object of a sub-class.
Note that the method of course only can access members declared in the
class of the parameter!! The parameter-reference doesn't "know
of" the
extended part in the object!
Note that this means that methods that takes parameters of the type Object can accept any object (as all objects inherits class Object) – but only access members declared in class Object (e.g. toString()). As usual it will be the member in the actual object that is accessed (e.g. an overridden toString() in the sub-class).
Sometimes it is necessary to know the exact type – perhaps to examine
if any of the extending members from sub-classes are available.
To determine
the actual type of an object use instanceof (see
figure 6.16 p. 387)
Polymorphism – as a reference might refer to a
sub-class object a call to a method through the reference might work differently
depending on the actual type of the object.
It's important to notice that
through a super-class reference you can only access the members that are
declared in the super-class, but you get the version from the sub-class!!
Contract - whenever you implement something there has
to be a purpose, i.e. somehow there is a plan and a goal. For a method
this can be described by pre-conditions (what must be true
before the method will work as expected - the methods requirements) and post-conditions (what
will be true after the method has done its work - the methods promise). You
could also see this as a contract - if you fulfill the requirements
(pre-conditions) then the method will fulfill the promise (post-conditions).
Abstract method - a method without body, i.e. only
the header is declared, but no implementation. The keyword abstract is
used to mark a method as abstract. Used
in interfaces and abstract classes. Ex.: public abstract
int calculate(int var); The public method calculate taking
an int parameter and returning an int is declared abstract. Note
the semicolon after the parameter-list- it terminates the definition before
any body (and thus code).
Interface - a structure that describes method headers
without defining the implementation.
An interface can only declare abstract
methods and constants (static final values). As there is no code an interface
can't be instantiated (no objects can be created). To use an interface
a regular class must implement it. To implement an interface the
class must provide the implementation of all the abstract classes from
the interface - they should off course be implemented the way they were
meant to be (according to their contract). So an interface should be described in
some documentation (e.g. comments in the file, javadoc or ...).
When a
class implements an interface it inherits the type - so the interface
can be used to declare the type for variables and parameters. An object
of the interface-type (implementing the interface) will fulfill the contract
of the interface as it is required to hold implementations of the methods
defined in the interface.
Whenever an object of the interface type is expected any object implementing
the interface can be used. Typically interfaces are used to make sure that,
perhaps otherwise unrelated, classes hold the same behavior in some limited
area. E.g. all classes implementing an interface declaring methods for
sorting can be sorted (provided the contracts from the interface are fulfilled)
even if these classes have nothing else in common.
A class can implement numerous interfaces (but only extend one (super)
class).
Abstract class - a class where at least one method
is abstract. Because there is no code for the abstract methods, you can't
instantiate an abstract class - the abstract class is meant to be extended
by a sub-class that provides implementation for the abstract methods
(fulfilling their contract).
Abstract classes are typically used when
a set of classes have a lot in common, but differs in a manner that is
very specific for each class (thus it's hard to define a default implementation).
A normal super-class would be able to hold all the common stuff, but to
make sure that every sub-class implements the special behavior you must
include an abstract method defining name, parameter-list and return type.
If the super-class had a "dummy" implementation of the method (with
an empty body) you could extend the class without having to override this
method. By making the method abstract you are sure that the sub-class must
define its own version of the method.