Expand|Select|Wrap|Line Numbers
- class Shape {
- public Shape() {
- }
- public double getArea() {
- return 5.0;
- }
- }
- class Circle extends Shape {
- double radius;
- public Circle(int radius) {
- this.radius = radius;
- }
- public double getArea() {
- return Math.PI * radius * radius;
- }
- }
- class Rectangle extends Shape {
- int length;
- int width;
- public Rectangle(int length, int width) {
- this.length = length;
- this.width = width;
- }
- public double getArea() {
- return length * width;
- }
- }
Access modifiers for an overriding method can allow more, but not less, access than the overridden method. i.e., a protected instance method in the super class can be made public, but not private, in the subclass. Remember that private methods are not accessible in subclasses and therefore cannot be overridden. If you want to override a method but want to use the result calculated by the super class version of the method you are overriding, then simply call that super class method using the keyword super as follows:
Expand|Select|Wrap|Line Numbers
- public double getArea() {
- return 5 + super.getArea();
- }
That is pretty much all there is about overriding!
Do not confuse overloading and overriding. Overloading occurs between methods in the same class with the same name but different signatures while overriding occurs between methods in different classes with one being the subclass of the other and the methods must have the same signature and return type or covariant return types.
If class A extends class B then variables of type B can hold references to objects of type A but not vice versa. That's the English version of it, the java code version of it is:
Expand|Select|Wrap|Line Numbers
- class B{
- }
- class A extends B{
- }
- then
Expand|Select|Wrap|Line Numbers
- B bVariable = new B(); //obviously allowed
- B bVariable = new A(); //also allowed
- A aVariable = new A();
- A aVariable = new B();//! incompatible types.
Hiding occurs when a static method in a class has the same signature and return type as one in that class' super class.
Expand|Select|Wrap|Line Numbers
- class B{
- public static void test() {
- System.out.println("test from b");
- }
- }
- class A extends B{
- public static void test() {
- System.out.println("test from a");
- }
- }
- public class Test{
- public static void main(String[] args) {
- B b = new B();
- B a = new A();
- b.test();
- a.test();
- }
- }
Expand|Select|Wrap|Line Numbers
- test from b
- test from b (this is not a typing error)
In the main method the two variables b and a share the same class, B, and so calling a class method on them calls the same method.
Expand|Select|Wrap|Line Numbers
- A a = new A();
- a.test();
The difference with instance methods becomes clear with
Expand|Select|Wrap|Line Numbers
- class B{
- public static void test() {
- System.out.println("test from b");
- }
- void testInst() {
- System.out.println("testInst from b");
- }
- }
- class A extends B{
- public static void test() {
- System.out.println("test from a");
- }
- void testInst() {
- System.out.println("testInst from a");
- }
- }
- public class ShapeTest{
- public static void main(String[] args) {
- B b = new B();
- B a = new A();
- b.test();
- a.test();
- b.testInst();
- a.testInst();
- }
- }
abstract keyword
A class can be declared abstract meaning that no objects can be created using that class.
Expand|Select|Wrap|Line Numbers
- abstract class A {
- }
- A a = new A();//!compile time error.
Expand|Select|Wrap|Line Numbers
- abstract class Shape {
- }
- class Circle extends Shape {
- }
Methods can be declared abstract as well in which case you don't provide the method body but leave that to inheriting subclasses. In the shapes example you know that
all shapes have a getArea method but cannot write any code for it because the implementation is different for each shape so declare the getArea() method in the shape class
because that's where it belongs (all shapes have a getArea method) but you leave it abstract because you don’t know how to write it yet.
Expand|Select|Wrap|Line Numbers
- abstract class Shape {
- public abstract double getArea();
- }
If a class contains an abstract method then that class is implicitly abstract and must the declared abstract otherwise the compiler will complain.
If a class inherits from an abstract class, then that class must provide implementations of all the abstract methods in the super class otherwise that inheriting class must also be declared abstract.
These things are not at all abstract and you should try them out on the compiler to see the effects.
Interfaces
An interface is a reference type whose members can be classes, other interfaces, constants and abstract methods.
They differ from classes in that they have no implementation. This is obvious since all their methods are abstract. Therefore all interfaces are abstract but you should not
put the public modifier. All interface members are implicitly public. Basically an interface is a contract that classes can choose to sign. Classes sign this contract by implementing the interface using the implements keyword.
Here are two example interfaces
Expand|Select|Wrap|Line Numbers
- interface Shape {
- double getArea();
- }
- interface Drawable {
- void draw();
- }
It is really as simple as that. Implement or else you're abstract, that's the rules of the contract. The interface is the boss. All this is checked at compile time.
Interfaces can declare constants as well which become available in implementing classes. A class can implement any number of interfaces. You can use this to achieve some level of multiple inheritance in Java by implementing multiple interfaces and thus being able to characterize an object into multiple groups. Here is an example. We want to be able to say that a Circle is a Drawable object and also that a Circle is a Shape.
Extending the Shape class says that a Circle is a shape. Extending the Drawable class says a Circle is a Drawable object. But we can only inherit from one class at a time so we make one of them an interface, implement it and
extend the other or we make both of them interfaces and implement them. The decision is ours, however, interfaces do not really provide any code reuse because they don't contain any implementations so it's wiser to choose a method that allow us the best in terms of code reuse. What interfaces provide is polymorphism. One interface, multiple implementations. By defining the Drawable interface, for example, we can implement it differently in all the classes that choose to implement this interface. If we had one method in some class draws shapes, we would simply need to pass an interface variable and call its draw method.
Expand|Select|Wrap|Line Numbers
- class Painter {
- void drawShape(Drawable d) {
- d.draw();
- }
- }