# Inheritance Polymorphism Using Overriding And Access Modifiers

## Inheritance

**Inheritance** is simply where one class inherits the *fields* and *methods* of another class. The class being inherited from is known as the **superclass** or **parent class**. The class doing the inheriting is known as the **subclass** or **child class**.

The main benefit of inheritance is it promotes *reusability* by allowing one class to re-use fields and methods that already exist in another class.

Here's the basic syntax for inheriting from another class:

```java
public class Animal {
  public void greeting() {
    System.out.println("I am an animal");
  }
}

public class Dog extends Animal {
  public static void main(String args[]) {
    Animal animal = new Animal();
    Dog dog = new Dog();
    
    animal.greeting();
    dog.greeting(); // has access to the same greeting via inheritance!
  }
}
```

## Overriding (as Part of Polymorphism)

Sometimes when a subclass inherits fields or methods from its parent class, you may want to **override** those fields or methods to support more custom behaviour.

### Overriding methods

To override an inherited method, you need to create a method according to the following rules:

* *Same signature* as the inherited method
* Return type must be the same too
* Overriding method *cannot be more private* than the inherited method

**Note**: As a best practice and to reduce errors, you can let the Java compiler know about a method override by including the `@Override` annotation above the method.

### Overriding `toString` and `equals`

It's generally best practice to always override `toString` and `equals`. This makes sense because printing a class or comparing it (especially during JUnit tests) tends to require unique implementations, and making sure these methods are accurate makes for easier debugging.

### Overriding constructors

Whenever a subclass runs a constructor, it automatically calls the superclass' *default zero-argument constructor* first.

```java
public class Foo extends Bar {
  public Foo() {
    super(); // calling `super` without any arguments happens automatically
  }
}
```

There are two ways you can override calling the superclass' default constructor:

```java
// 1. Call `super` with a different method signature
public class Foo extends Bar {
  public Foo() {
    super(true); // calls superclass constructor with boolean as single parameter 
  }
}

// 2. Completely ignore superclass constructors by calling sublass constructor
public class Foo extends Bar {
  public Foo() {
    this(true, 1, 2); // calls own constructor instead
  }
}
```

**Important**: Whenever explicitly invoking a superclass' constructor using `super`, it must always be the *first* thing you do.

### Calling overriden methods

Technically, when you override a method, Java basically hides it. You can actually still call it via `super`:

```java
public class Animal {
  public void greeting() {
    System.out.println("I am an animal");
  }
}

public class Dog extends Animal {
  @Override
  public void greeting() {
  super.greeting();
    System.out.println("I am a dog"); 
  }
  
  public static void main(String args[]) {
    Dog dog = new Dog();
    // Prints "I am an animal" and then "I am a dog"
    dog.greeting();
  }
}
```

**Pro tip**: You will usually call an overriden method when you want to keep the original functionality of the overriden method but just *add* more to it.

## Access Modifiers

**Access modifiers** are keywords that restrict the scope of a class, constructor, field, or method.

There are four types of access modifiers:

* `public`
  * Accessible from anywhere in the program
* `protected`
  * Accessible within the same package or via subclasses in a different package
* `default` (the default permissions when no access modifier is specified)
  * Accessible only within the same package
* `private`
  * Accessible only within the same class it's declared

### Choosing access modifiers

Here are some general principles to help you pick the right access modifier:

* Start with the most restrictive access modifier that makes sense for what you're defining
* Use `private` unless you have a good reason not to
* Avoid `public` as much as reasonably possible

### Getters and setters

The purpose of getters and setters is to usually access `private` or `protected` variables.

This design pattern is known as **encapsulation**: you hide a field from anything outside of the class to ensure people don't get caught up in your implementation. Instead, they get what they need via getters and setters.

**Importance**: This gives you the flexibility to edit your code more easily, as it's now more flexible.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://notes.danfitz.com/java/inheritance-data-structures-java/a-inheritance-polymorphism-using-overriding-access-modifiers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
