# Design Hints for Inheritance in Java

**Some hints that we have found useful when using inheritance.**


### I.  Place common operations and fields in the superclass.

Instead of replicating each field in subclasses, we should put common fields and methods on the superclass.


### II. Don’t use protected fields

Some programmers think it is a good idea to define most instance fields as protected, “*just in case*” so that subclasses can access these fields if they need to. However, the protected mechanism doesn’t give much protection, for two reasons:

- The set of subclasses is **unbounded** - anyone can form a subclass of your classes and then write code that **directly accesses **protected instance fields instead of using getter methods, thereby **breaking encapsulation**.
- In Java, all classes in the **same package** have **access to protected fields**, whether or not they are subclasses.


### III. Use inheritance to model the “*is–a*” relationship.

Inheritance is a handy code-saver, but sometimes people overuse it.  For example, suppose we need a **Contractor** class. **Contractors** have names and hire dates, but they **do not** have **salaries**. Instead, they are **paid by the hour**, and they do not stay around long enough to get a raise.

There is the temptation to form a subclass **Contractor** from **Employee** and add an
**hourlyWage** field.


```
public class Employee {
   private double salary;
   private LocalDate hiredDate;
}

public class Contractor extends Employee {
   private double hourlyWage;
   . . .
}
``` 

Look good, right? 

But this is not a good idea, because now each **contractor** object has both a **salary** and **hourly wage** field.

The **contractor-employee** relationship fails the “*is–a*” test. A **contractor** is
not a special case of an **employee**.

### IV. Don’t use *inheritance* unless all inherited methods make sense.

If you find any method in **superclass** which is not appropriate or doesn't make sense in the **subclass**, **inheritance** is not appropriate.


### V. Don’t change the expected behavior when you override a method.

The **substitution principle** applies not just to the syntax but, more importantly, to **behavior**. When you override a method, you should not **unreasonably change** its behavior. The compiler can’t help you - it cannot check whether your redefinitions make sense. 

Technical debt and bugs come from here :)))


### VI. Use polymSourceorphism, not type information.

Whenever you find code of the form

```
if (x is of type 1)
  action1(x);
else if (x is of type 2)
  action2(x);
``` 

think about **polymorphism**.

Do *action1* and *action2* represent a common concept? If so, make the concept a method of a common **superclass** or **interface** of both types. Then, you can simply call:

```
x.action();
```
Code that uses **polymorphic** methods or **interface** implementations is much
easier to *maintain* and *extend* than code using **multiple type** tests.

### VII. Don’t overuse reflection.

The **reflection** mechanism lets you write programs with amazing generality, by detecting fields and methods **at runtime**. This capability can be extremely useful for **systems programming**, but it is usually **not appropriate** in **applications**. Reflection is **fragile**—with it, the compiler cannot help you find programming errors. Any errors are found at runtime and result in exceptions.



(Source : Core Java Volumn I - Fundamentals)



