Topic 8 of 28 · Android Native Developer

Inheritance in Java

Lesson TL;DRTopic 8: Inheritance in Java 📖 5 min read · 🎯 intermediate · 🧭 Prerequisites: polymorphisminjava, androidbuildingblocksivcontentproviders Why this matters Here's the thing — you've already used inh...
5 min read·intermediate·java · inheritance · android · object-oriented-programming

Topic 8: Inheritance in Java

📖 5 min read · 🎯 intermediate · 🧭 Prerequisites: polymorphism-in-java, android-building-blocks-iv-content-providers

Why this matters

Here's the thing — you've already used inheritance without knowing it. Every time you create a new Activity in Android Studio, it says extends AppCompatActivity. That word extends is not decoration. It means your class is borrowing hundreds of built-in features — a screen lifecycle, a back button, a title bar — without you writing a single line to make them work. That's inheritance in action. In this lesson we'll understand exactly what's happening under the hood, so when Android gives you a class to extend, you know what you're getting and why it works.

What You'll Learn

  • How to define a superclass (base class) and a subclass (derived class) in Java
  • How to inherit and reuse methods from a BaseActivity across multiple Android activities
  • How to create custom Android UI components by extending existing view classes like AppCompatButton
  • How to use inherited methods and override them to add custom behavior

The Analogy

Think of a city's building code. The master blueprint defines everything every building must have: load-bearing walls, plumbing hookups, electrical panels. When architects design a library, a school, or a fire station, they start from that master blueprint and add only what makes their building unique — they do not redraw the foundation from scratch. In Java, the superclass is the master blueprint, and each subclass is a specialized building that inherits the foundation and adds its own rooms. Every library still has walls and plumbing; every MainActivity still has showToast and logMessage.

Chapter 1: The Fundamentals of Inheritance

In Java, inheritance allows a class called the subclass (or derived class) to inherit fields and methods from another class called the superclass (or base class). This enables two key benefits:

  • Code reuse — common logic lives in one place, not duplicated across every class
  • Hierarchical modeling — relationships like "a MainActivity IS-A BaseActivity" map naturally to the class tree

The keyword that makes this happen is extends. The subclass declares extends SuperclassName, and from that moment it owns every non-private field and method the superclass defines.

public class SubClass extends SuperClass {
    // inherits all public and protected members of SuperClass
}

The super keyword lets a subclass call its parent's constructors or methods — essential when you need the parent's setup logic before adding your own.

Chapter 2: Inheriting Activity Behavior — BaseActivity and MainActivity

Imagine building an Android app with a dozen screens. Every screen needs to show toast messages and write log entries. Without inheritance you copy those methods into every Activity. With inheritance you write them once.

1. Base Class: BaseActivity

BaseActivity extends AppCompatActivity (itself part of Android's own inheritance chain) and defines two reusable utilities.

// BaseActivity.java
public class BaseActivity extends AppCompatActivity {

    // Common method to show a toast message
    public void showToast(String message) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    }

    // Common method to log a message
    public void logMessage(String tag, String message) {
        Log.d(tag, message);
    }
}

2. Subclass: MainActivity

MainActivity extends BaseActivity and immediately has access to both utilities — no redeclaration needed.

// MainActivity.java
public class MainActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Using the inherited method to show a toast message
        showToast("Welcome to MainActivity");

        // Using the inherited method to log a message
        logMessage("MainActivity", "Activity created");
    }
}

super.onCreate(savedInstanceState) calls AppCompatActivity's own onCreate through the chain — skipping it would break Android's lifecycle. The rest of onCreate then calls showToast and logMessage as if they were declared locally, because through inheritance they effectively are.

Chapter 3: Inheritance in Android UI Components

Android's UI system is one of the largest real-world inheritance hierarchies in production software. View is the superclass of every visible element. From it descends TextView, from TextView descends Button, and so on. Every widget in your layout inherits drawing, event handling, and measurement from View without those classes duplicating a line of that logic.

classDiagram
    View <|-- TextView
    TextView <|-- Button
    Button <|-- AppCompatButton
    AppCompatButton <|-- CustomButton

This hierarchy means you can extend any existing widget and inherit its complete behavior, then override or add exactly what you need.

Chapter 4: Building a Custom View by Extending AppCompatButton

When a standard Button does not meet your needs, you extend it. The subclass inherits all click-handling, layout, and drawing behavior, then layers on custom initialization and behavior.

1. Custom Button Class

// CustomButton.java
public class CustomButton extends androidx.appcompat.widget.AppCompatButton {

    public CustomButton(Context context) {
        super(context);
        init();
    }

    public CustomButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CustomButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        // Custom initialization code
        setBackgroundColor(Color.BLUE);
        setTextColor(Color.WHITE);
        setText("Custom Button");
    }

    @Override
    public boolean performClick() {
        // Custom click behavior layered on top of the parent's click
        Toast.makeText(getContext(), "Custom Button Clicked", Toast.LENGTH_SHORT).show();
        return super.performClick();
    }
}

Three constructors are provided because Android's inflation system calls different constructors depending on whether the view is created programmatically or inflated from XML. Each delegates to super(...) first — ensuring AppCompatButton's internals are fully set up — then calls init() for the custom styling. performClick is overridden to inject a toast, then calls super.performClick() so accessibility events and standard listener callbacks still fire.

2. Using CustomButton in a Layout

<!-- activity_main.xml -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.example.myapp.CustomButton
        android:id="@+id/custom_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"/>

</RelativeLayout>

The fully qualified class name com.example.myapp.CustomButton tells the layout inflater which class to instantiate. Android calls the two-argument constructor (Context, AttributeSet) during inflation.

3. Activity Code

// MainActivity.java
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        CustomButton customButton = findViewById(R.id.custom_button);
        customButton.setOnClickListener(v -> {
            // Additional behavior on click can also be added here
            customButton.performClick();
        });
    }
}

findViewById returns the inflated CustomButton instance. The OnClickListener can add further logic at the call site while performClick still fires the in-class toast defined in CustomButton itself.

🧪 Try It Yourself

Task: Create a BaseActivity with a showToast helper, then build two subclasses — HomeActivity and ProfileActivity — each of which calls showToast from its onCreate with a screen-specific message.

Success criterion: Launch either activity in the emulator and see a toast appear with the correct screen name — no Toast.makeText call inside HomeActivity or ProfileActivity itself.

Starter snippet:

// BaseActivity.java
public class BaseActivity extends AppCompatActivity {
    public void showToast(String message) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    }
}

// HomeActivity.java
public class HomeActivity extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        showToast("You are on Home"); // inherited — no import needed
    }
}

Repeat the pattern for ProfileActivity. Add both to AndroidManifest.xml and navigate between them to watch each toast fire.

🔍 Checkpoint Quiz

Q1. What is the purpose of calling super.onCreate(savedInstanceState) inside an overridden onCreate method?

A) It compiles the layout XML file
B) It triggers the parent class's lifecycle setup, which Android requires
C) It registers the activity in the manifest
D) It inflates the view hierarchy automatically

Q2. Given this snippet, what happens when customButton.performClick() is called?

@Override
public boolean performClick() {
    Toast.makeText(getContext(), "Custom Button Clicked", Toast.LENGTH_SHORT).show();
    return super.performClick();
}

A) Only the toast shows; the standard click event is suppressed
B) A toast shows and then the parent's click handling (including registered listeners) fires
C) The method throws an exception because super.performClick() is deprecated
D) Nothing happens until setOnClickListener is also called on the instance

Q3. Why does CustomButton declare three constructors instead of one?

A) Java requires every class to have three constructors
B) Android's layout inflater selects different constructors for programmatic vs. XML creation
C) Each constructor handles a different screen density
D) AppCompatButton forces subclasses to declare all three

Q4. You are building a news app with twelve screens. Every screen must display a loading spinner and log analytics events on launch. How would you use inheritance to avoid duplicating that logic?

A1. B — Android's AppCompatActivity (and its parent chain) performs critical lifecycle wiring inside onCreate. Skipping super.onCreate leaves the activity in a broken state.

A2. B — The override adds the toast first, then return super.performClick() delegates to AppCompatButton's implementation, which dispatches click events to any registered OnClickListener and fires accessibility actions.

A3. B — The Android view inflation system calls the (Context, AttributeSet) constructor when it reads XML, while code that creates a view directly uses (Context). The third constructor (Context, AttributeSet, int) handles style attributes. Providing all three ensures the custom view works in every instantiation path.

A4. Create a BaseActivity extends AppCompatActivity with a showLoadingSpinner() method and an onLaunchAnalytics(String screenName) method. Have every screen activity extend BaseActivity and call those inherited methods from onCreate. This way the spinner and analytics logic live in exactly one place; changing them updates all twelve screens simultaneously.

🪞 Recap

  • A subclass declared with extends inherits all public and protected fields and methods from its superclass, enabling reuse without duplication.
  • super(...) delegates to the parent constructor; super.methodName() calls the parent's version of an overridden method — both are essential for preserving parent behavior.
  • Android Activities commonly share a BaseActivity that centralizes cross-cutting concerns like toasts, logging, or analytics.
  • Android's entire UI system is an inheritance hierarchy rooted at View; every widget you use is already a subclass, and you can extend any of them to create custom components.
  • Overriding a method (e.g., performClick) lets a subclass specialize behavior while super.performClick() ensures the parent's contract is still honored.

📚 Further Reading

Like this topic? It’s one of 28 in Android Native Developer.

Block your seat for ₹2,500 and join the next cohort.