Inheritance, Interfaces, and Polymorphism

Parent Construction, `super`, and Inherited Access

ReadingPreview

You are viewing a free preview lesson.

Lesson Overview

একটি child object তৈরি করলে শুধু child class-এর constructor execute হয় না।

তার parent অংশও initialize হতে হয়।

Consider:

VideoLesson videoLesson =
        new VideoLesson(
                1L,
                "Inheritance Basics",
                "https://cdn.liveklass.io/videos/inheritance",
                18
        );

VideoLesson একটি ContentItem

তাই objectটির মধ্যে conceptually দুই ধরনের state আছে:

ContentItem state:
id
title
published

VideoLesson state:
videoUrl
durationInMinutes

VideoLesson constructor শুধু video-specific state initialize করলেই যথেষ্ট নয়।

Parent-এর required stateও validভাবে initialize করতে হবে।

এই কাজের জন্য Java super(...) ব্যবহার করে।

এই lesson-এ আমরা শিখব:

  • Parent constructor কেন execute হয়
  • super(...)
  • Automatic super()
  • Constructor execution order
  • Parent constructor validation
  • this(...) এবং super(...)
  • Inherited members
  • Parent-এর private state
  • protected access
  • কেন fields সাধারণত private রাখা ভালো
  • final method এবং final class
  • Safe inheritance API design

Learning Objectives

এই lesson শেষ করার পর আপনি পারবেন:

  • Child object creation-এর সময় parent constructor কেন প্রয়োজন explain করতে
  • super(...) দিয়ে parent constructor call করতে
  • Automatic super() কখন add হয় বুঝতে
  • Parent এবং child constructor execution order predict করতে
  • this(...) এবং super(...)-এর relationship explain করতে
  • Parent-এর private fields child direct access করতে পারে না কেন বুঝতে
  • Inherited public এবং protected members ব্যবহার করতে
  • protected field-এর design risk explain করতে
  • final method দিয়ে overriding prevent করতে
  • final class দিয়ে inheritance prevent করতে

A Child Object Contains Parent State

Parent class:

public class ContentItem {

    private final long id;
    private final String title;

    private boolean published;

    public ContentItem(
            long id,
            String title
    ) {
        if (id <= 0) {
            throw new IllegalArgumentException(
                    "Content ID must be positive."
            );
        }

        if (
                title == null
                || title.isBlank()
        ) {
            throw new IllegalArgumentException(
                    "Content title is required."
            );
        }

        this.id = id;
        this.title = title.strip();
        this.published = false;
    }
}

Child class:

public class VideoLesson
        extends ContentItem {

    private final String videoUrl;
    private final int durationInMinutes;
}

A VideoLesson object-এর নিজের fields:

videoUrl
durationInMinutes

এবং inherited parent state:

id
title
published

থাকে।

তাই child object creation-এর সময় parent portion initialize হওয়া বাধ্যতামূলক।


Calling the Parent Constructor

Child constructor থেকে parent constructor call করতে:

super(...)

Example:

public class VideoLesson
        extends ContentItem {

    private final String videoUrl;
    private final int durationInMinutes;

    public VideoLesson(
            long id,
            String title,
            String videoUrl,
            int durationInMinutes
    ) {
        super(
                id,
                title
        );

        this.videoUrl =
                videoUrl;

        this.durationInMinutes =
                durationInMinutes;
    }
}

এখানে:

super(
        id,
        title
);

ContentItem(long, String) constructor call করছে।


Why super(...) Is Necessary

Parent class fields:

private final long id;
private final String title;

Child class directভাবে এগুলো assign করতে পারে না।

Wrong:

public VideoLesson(
        long id,
        String title
) {
    this.id = id;
    this.title = title;
}

Compile হবে না।

কারণ:

  • id এবং title ContentItem-এর private fields
  • Field initialization parent class-এর responsibility
  • Parent constructor validationও preserve করতে হবে

Correct:

super(
        id,
        title
);

Parent নিজের state নিজে initialize করে।


Parent Validation Is Reused

Parent constructor:

public ContentItem(
        long id,
        String title
) {
    if (id <= 0) {
        throw new IllegalArgumentException(
                "Content ID must be positive."
        );
    }

    if (
            title == null
            || title.isBlank()
    ) {
        throw new IllegalArgumentException(
                "Content title is required."
        );
    }

    this.id = id;
    this.title = title.strip();
}

Child constructor:

public VideoLesson(
        long id,
        String title,
        String videoUrl,
        int durationInMinutes
) {
    super(
            id,
            title
    );

    // Child validation
}

এখন প্রতিটি child class-এ parent validation duplicate করতে হচ্ছে না।

VideoLesson
ArticleLesson
QuizLesson

সবাই same parent creation rules follow করবে।


Constructor Execution Order

Child object তৈরি হলে constructor execution parent থেকে child-এর দিকে যায়।

Example hierarchy:

Object
└── ContentItem
    └── VideoLesson

Creation:

new VideoLesson(...);

Conceptual execution order:

1. Object constructor
2. ContentItem constructor
3. VideoLesson constructor

Java সবসময় parent state আগে initialize করে।

তারপর child-specific initialization complete করে।


Observing Constructor Order

public class ContentItem {

    public ContentItem(
            long id,
            String title
    ) {
        System.out.println(
                "ContentItem constructor"
        );
    }
}
public class VideoLesson
        extends ContentItem {

    public VideoLesson(
            long id,
            String title
    ) {
        super(
                id,
                title
        );

        System.out.println(
                "VideoLesson constructor"
        );
    }
}

Usage:

new VideoLesson(
        1L,
        "Inheritance"
);

Output:

ContentItem constructor
VideoLesson constructor

Parent constructor body আগে execute হয়েছে।


Why Parent Runs First

Child class parent state এবং behavior-এর ওপর depend করতে পারে।

Example:

public class VideoLesson
        extends ContentItem {

    public VideoLesson(
            long id,
            String title
    ) {
        super(
                id,
                title
        );

        System.out.println(
                getTitle()
        );
    }
}

getTitle() meaningful result দিতে parent title আগে initialize হওয়া প্রয়োজন।

Initialization order object-কে partially initialized parent state থেকে protect করে।


super(...) Must Be the First Statement

Wrong:

public VideoLesson(
        long id,
        String title
) {
    System.out.println(
            "Creating video"
    );

    super(
            id,
            title
    );
}

Compile হবে না।

Correct:

public VideoLesson(
        long id,
        String title
) {
    super(
            id,
            title
    );

    System.out.println(
            "Creating video"
    );
}

Constructor chaining call সবসময় first statement হতে হয়।


Automatic super()

যদি child constructor explicit super(...) না লেখে, compiler first statement হিসেবে:

super();

add করার চেষ্টা করে।

Example:

public class ContentItem {

    public ContentItem() {
    }
}
public class VideoLesson
        extends ContentItem {

    public VideoLesson() {
    }
}

Child constructor conceptually:

public VideoLesson() {
    super();
}

When Automatic super() Fails

Parent class:

public class ContentItem {

    public ContentItem(
            long id,
            String title
    ) {
    }
}

Parent-এর no-argument constructor নেই।

Child:

public class VideoLesson
        extends ContentItem {

    public VideoLesson() {
    }
}

Compiler automaticভাবে:

super();

call করতে চাইবে।

কিন্তু ContentItem() constructor নেই।

তাই compile error হবে।

Correct child constructor:

public VideoLesson(
        long id,
        String title
) {
    super(
            id,
            title
    );
}

Compiler-Provided Parent Constructor

Previous module থেকে rule:

কোনো class-এ constructor declare না করা হলে compiler একটি no-argument constructor provide করে।

Parent:

public class ContentItem {

}

Compiler conceptually provides:

public ContentItem() {
}

তাই child constructor explicit super() ছাড়া compile করতে পারে।

কিন্তু parent-এ parameterized constructor add করলে automatic no-argument constructor আর থাকে না।


Do Not Add a Weak No-Argument Constructor Just to Satisfy Inheritance

Problem solve করার জন্য কেউ parent-এ লিখতে পারে:

public ContentItem() {
}

এতে child compile করবে।

কিন্তু parent required state হারাতে পারে:

id = 0
title = null

এটি invalid object creation allow করতে পারে।

Better:

public VideoLesson(
        long id,
        String title
) {
    super(
            id,
            title
    );
}

Parent invariants weaken করে inheritance convenient করা উচিত নয়।


Parent Constructor Is Not Inherited

Child class parent constructor inherit করে না।

Parent:

public ContentItem(
        long id,
        String title
) {
}

এই কারণে automatically child-এর এমন constructor পাওয়া যাবে না:

new VideoLesson(
        1L,
        "Inheritance"
);

Child-কে নিজের constructor declare করতে হয়।

public VideoLesson(
        long id,
        String title
) {
    super(
            id,
            title
    );
}

Methods inherited হতে পারে।

Constructors inherited হয় না।


Child Constructor Can Add More Required State

Parent state:

id
title

Child state:

videoUrl
durationInMinutes

Complete constructor:

public VideoLesson(
        long id,
        String title,
        String videoUrl,
        int durationInMinutes
) {
    super(
            id,
            title
    );

    if (
            videoUrl == null
            || videoUrl.isBlank()
    ) {
        throw new IllegalArgumentException(
                "Video URL is required."
        );
    }

    if (durationInMinutes <= 0) {
        throw new IllegalArgumentException(
                "Video duration must be positive."
        );
    }

    this.videoUrl =
            videoUrl.strip();

    this.durationInMinutes =
            durationInMinutes;
}

Validation ownership:

ContentItem validates:
id
title

VideoLesson validates:
videoUrl
durationInMinutes

প্রতিটি class নিজের state-এর rules own করছে।


Multiple Parent Constructors

Parent class multiple constructors expose করতে পারে।

public class ContentItem {

    private final long id;
    private final String title;
    private final boolean published;

    public ContentItem(
            long id,
            String title
    ) {
        this(
                id,
                title,
                false
        );
    }

    public ContentItem(
            long id,
            String title,
            boolean published
    ) {
        this.id = id;
        this.title = title;
        this.published =
                published;
    }
}

Child matching parent constructor choose করতে পারে।

public VideoLesson(
        long id,
        String title
) {
    super(
            id,
            title
    );
}

অথবা:

public VideoLesson(
        long id,
        String title,
        boolean published
) {
    super(
            id,
            title,
            published
    );
}

তবে child constructor যেন parent lifecycle rule bypass না করে।

যদি content শুধু publish() method-এর মাধ্যমে publish হওয়া উচিত হয়, constructor দিয়ে arbitrary published state expose করা weak design হতে পারে।


this(...) and super(...)

Previous module-এ আমরা constructor chaining-এর জন্য this(...) শিখেছি।

this(...)

same class-এর অন্য constructor call করে।

super(...)

parent class-এর constructor call করে।


They Cannot Both Be First

A constructor-এ first statement একটিই হতে পারে।

Invalid:

public VideoLesson(
        long id,
        String title
) {
    this(
            id,
            title,
            "default-url",
            1
    );

    super(
            id,
            title
    );
}

Compile হবে না।

যদি this(...) call করেন, delegated constructor eventually super(...) call করবে।


Valid Constructor Chaining

public class VideoLesson
        extends ContentItem {

    private final String videoUrl;
    private final int durationInMinutes;

    public VideoLesson(
            long id,
            String title,
            String videoUrl
    ) {
        this(
                id,
                title,
                videoUrl,
                1
        );
    }

    public VideoLesson(
            long id,
            String title,
            String videoUrl,
            int durationInMinutes
    ) {
        super(
                id,
                title
        );

        if (
                videoUrl == null
                || videoUrl.isBlank()
        ) {
            throw new IllegalArgumentException(
                    "Video URL is required."
            );
        }

        if (durationInMinutes <= 0) {
            throw new IllegalArgumentException(
                    "Duration must be positive."
            );
        }

        this.videoUrl =
                videoUrl.strip();

        this.durationInMinutes =
                durationInMinutes;
    }
}

Flow:

Three-argument VideoLesson constructor
→ Four-argument VideoLesson constructor
→ ContentItem constructor

Actual execution order still:

ContentItem initialization
VideoLesson initialization

Inherited Members

Child object parent-এর accessible members use করতে পারে।

Parent:

public class ContentItem {

    private final String title;

    public String getTitle() {
        return title;
    }

    public boolean publish() {
        return true;
    }
}

Child:

public class VideoLesson
        extends ContentItem {

    public void printTitle() {
        System.out.println(
                getTitle()
        );
    }
}

getTitle() inherited public method।


Private Members Are Part of the Object but Not Directly Accessible

Parent:

private final String title;

Child object-এর মধ্যে title state আছে।

কিন্তু child class direct access করতে পারে না।

Invalid:

public void printTitle() {
    System.out.println(
            title
    );
}

কারণ title parent-এর private implementation detail।

Valid:

public void printTitle() {
    System.out.println(
            getTitle()
    );
}

Parent controlled method expose করেছে।


Private Does Not Mean “Not Inherited” in the Physical Sense

একটি common oversimplification:

Private fields are not inherited.

Better mental model:

  • Child object-এর parent portion-এ private state exists
  • Child class source code সেই field direct access করতে পারে না
  • Parent public বা protected methods সেই state access করতে পারে
  • Child inherited methods use করে state-এর সঙ্গে interact করতে পারে

Example:

videoLesson.publish();

publish() parent-এর private published field change করতে পারে।

Child method নিজে fieldটি direct access করতে পারে না।


Using Parent Queries Instead of Exposing Fields

Parent:

public boolean isPublished() {
    return published;
}

Child:

public boolean canStartPlayback() {
    return isPublished();
}

এতে parent state encapsulated থাকে।

Child parent-এর public contract use করছে।


The protected Modifier

protected member:

  • Same package থেকে accessible
  • Subclasses থেকে accessible
  • Cross-package subclass access-এর কিছু specific rules আছে

Example:

protected String getContentTypeLabel() {
    return "Content";
}

Child:

public class VideoLesson
        extends ContentItem {

    public void printType() {
        System.out.println(
                getContentTypeLabel()
        );
    }
}

Protected Fields

Technically:

public class ContentItem {

    protected String title;
}

Child direct access করতে পারে।

public class VideoLesson
        extends ContentItem {

    public void renameInternally(
            String title
    ) {
        this.title =
                title;
    }
}

কিন্তু এতে encapsulation দুর্বল হয়।

Child:

  • Validation bypass করতে পারে
  • Parent invariant ভাঙতে পারে
  • Parent implementation-এর সঙ্গে tightly coupled হয়
  • Field representation change হলে break করতে পারে

Prefer Private Fields with Protected Behavior

Weak:

protected String title;

Stronger:

private String title;

protected final boolean hasValidTitle() {
    return title != null
            && !title.isBlank();
}

অথবা:

protected final String getTitleForSubclass() {
    return title;
}

তবে public getter already appropriate হলে separate protected getter প্রয়োজন নেই।

Best choice depend করে parent API design-এর ওপর।


Protected Methods as Extension Points

Parent intentionally child customization allow করতে পারে।

public class ContentItem {

    public boolean publish() {
        if (!canPublish()) {
            return false;
        }

        return markAsPublished();
    }

    protected boolean canPublish() {
        return true;
    }

    private boolean markAsPublished() {
        return true;
    }
}

Child:

public class VideoLesson
        extends ContentItem {

    @Override
    protected boolean canPublish() {
        return hasVideoUrl();
    }
}

এখানে protected method একটি deliberate extension point।

তবে overriding এবং template behavior Lesson 3 ও Lesson 4-এ বিস্তারিত শেখানো হবে।


protected Should Be Intentional

কোনো member protected করার অর্থ:

Subclasses এই member-এর ওপর depend করতে পারে।

এটি inheritance API-এর অংশ।

Future parent refactoring harder হতে পারে।

Ask:

  • Child-এর কি সত্যিই এই behavior প্রয়োজন?
  • Public method যথেষ্ট কি?
  • Private helper দিয়ে parent নিজেই rule enforce করতে পারে কি?
  • Composition better কি?
  • আমরা কি accidental subclass API তৈরি করছি?

Package-Private and Inheritance

No modifier:

boolean validateTitle() {
}

এটি package-private।

Same package-এর child access করতে পারে।

Different package-এর child direct access করতে পারে না।

Example:

io.liveklass.content.ContentItem
io.liveklass.video.VideoLesson

যদি method package-private হয়, VideoLesson access করতে পারবে না।

Package organization inheritance visibility affect করে।


Public Members

Public parent methods সব child objects-এর public API-এর অংশ হয়ে যায়।

Parent:

public boolean publish() {
}

Child object:

videoLesson.publish();

এটি inherited public operation।

এই কারণে parent public API carefully design করা জরুরি।

একটি method parent-এ public করলে সব current এবং future child types সেই contract inherit করতে পারে।


Parent API Should Be Valid for Every Child

Suppose parent:

public void download() {
}

কিন্তু LiveStreamLesson download support করে না।

Child যদি লিখতে বাধ্য হয়:

@Override
public void download() {
    throw new UnsupportedOperationException();
}

তাহলে parent contract হয়তো too broad।

Better design হতে পারে:

interface Downloadable

শুধু downloadable content types implement করবে।

Interfaces Lesson 4-এ শেখানো হবে।


The final Method

Parent method final হলে child override করতে পারে না।

public final long getId() {
    return id;
}

Child:

@Override
public long getId() {
    return 999L;
}

Compile হবে না।


Why Make a Method Final?

A method final হতে পারে যখন:

  • Parent invariant depend করে
  • Behavior বদলানো unsafe
  • Identity rule consistent থাকা দরকার
  • Security বা lifecycle step override হওয়া উচিত নয়
  • Parent algorithm stable রাখতে হয়

Example:

public final boolean isPublished() {
    return published;
}

তবে every method final করলে inheritance usefulness কমে।

Only deliberate non-overridable behavior final করুন।


Final Method and Encapsulation

Suppose parent identity:

private final long id;

public final long getId() {
    return id;
}

Child identity query redefine করতে পারবে না।

এতে parent contract stable থাকে।

কিন্তু getter final করা সবসময় প্রয়োজন নয়।

Design risk real হলে ব্যবহার করুন।


The final Class

A class final হলে extend করা যায় না।

public final class CourseCode {

}

Invalid:

public class SpecialCourseCode
        extends CourseCode {

}

Compile হবে না।


Why Make a Class Final?

A class final হতে পারে যখন:

  • Class immutable contract protect করতে হবে
  • Inheritance meaningful নয়
  • Security-sensitive behavior alter করা উচিত নয়
  • Value object specialization invalid
  • Class extension-এর জন্য designed হয়নি
  • Composition preferred

Examples:

public final class CourseCode
public final class Money

Value object-এর equality এবং immutability subclass দিয়ে দুর্বল হওয়া prevent করা যায়।


Non-Final Class Is an Extension Decision

A class final না হলে technically extend করা যায়।

কিন্তু technically extendable হওয়া মানেই class inheritance-এর জন্য well-designed নয়।

Inheritance-friendly class design require করে:

  • Stable protected/public contract
  • Documented invariants
  • Safe override points
  • Constructor rules
  • Equality considerations
  • Substitutability

Public class automatically good base class নয়।


Engineering Note: Design for Inheritance or Prevent It

A useful principle:

A classকে inheritance-এর জন্য deliberately design করুন, অথবা inheritance prevent করার কথা বিবেচনা করুন।

Accidental inheritance risky।

Parent changes children break করতে পারে।

Child overrides parent assumptions violate করতে পারে।

Internal domain classes-এর ক্ষেত্রে:

  • final class
  • Interfaces
  • Composition

অনেক সময় safer choice।


A Complete Example

ContentItem.java

public class ContentItem {

    private final long id;
    private final String title;

    private boolean published;

    public ContentItem(
            long id,
            String title
    ) {
        if (id <= 0) {
            throw new IllegalArgumentException(
                    "Content ID must be positive."
            );
        }

        if (
                title == null
                || title.isBlank()
        ) {
            throw new IllegalArgumentException(
                    "Content title is required."
            );
        }

        this.id = id;
        this.title = title.strip();
        this.published = false;
    }

    public final long getId() {
        return id;
    }

    public final String getTitle() {
        return title;
    }

    public final boolean isPublished() {
        return published;
    }

    public boolean publish() {
        if (published) {
            return false;
        }

        if (!canPublish()) {
            return false;
        }

        published = true;

        return true;
    }

    protected boolean canPublish() {
        return true;
    }
}

VideoLesson.java

public class VideoLesson
        extends ContentItem {

    private final String videoUrl;
    private final int durationInMinutes;

    public VideoLesson(
            long id,
            String title,
            String videoUrl
    ) {
        this(
                id,
                title,
                videoUrl,
                1
        );
    }

    public VideoLesson(
            long id,
            String title,
            String videoUrl,
            int durationInMinutes
    ) {
        super(
                id,
                title
        );

        if (
                videoUrl == null
                || videoUrl.isBlank()
        ) {
            throw new IllegalArgumentException(
                    "Video URL is required."
            );
        }

        if (durationInMinutes <= 0) {
            throw new IllegalArgumentException(
                    "Video duration must be positive."
            );
        }

        this.videoUrl =
                videoUrl.strip();

        this.durationInMinutes =
                durationInMinutes;
    }

    @Override
    protected boolean canPublish() {
        return videoUrl.startsWith(
                "https://"
        );
    }

    public String getVideoUrl() {
        return videoUrl;
    }

    public int getDurationInMinutes() {
        return durationInMinutes;
    }
}

canPublish() override এখানে শুধু preview।

Method overriding পরবর্তী lesson-এ বিস্তারিত explain করা হবে।


ArticleLesson.java

public class ArticleLesson
        extends ContentItem {

    private final String content;

    public ArticleLesson(
            long id,
            String title,
            String content
    ) {
        super(
                id,
                title
        );

        if (
                content == null
                || content.isBlank()
        ) {
            throw new IllegalArgumentException(
                    "Article content is required."
            );
        }

        this.content =
                content.strip();
    }

    @Override
    protected boolean canPublish() {
        return content.length()
                >= 20;
    }

    public String getContent() {
        return content;
    }
}

Main.java

public class Main {

    public static void main(
            String[] args
    ) {
        VideoLesson video =
                new VideoLesson(
                        1L,
                        "Parent Construction",
                        "https://cdn.liveklass.io/videos/super",
                        15
                );

        ArticleLesson article =
                new ArticleLesson(
                        2L,
                        "Inherited Access",
                        "Private state should remain encapsulated."
                );

        System.out.println(
                video.publish()
        );

        System.out.println(
                article.publish()
        );

        System.out.println(
                video.getTitle()
        );

        System.out.println(
                article.getTitle()
        );
    }
}

Possible output:

true
true
Parent Construction
Inherited Access

Construction Flow of VideoLesson

Creation:

new VideoLesson(
        1L,
        "Parent Construction",
        "https://cdn.liveklass.io/videos/super",
        15
);

Flow:

1. VideoLesson four-argument constructor selected
2. super(id, title) invoked
3. ContentItem validates id
4. ContentItem validates title
5. ContentItem initializes id, title, published
6. Control returns to VideoLesson constructor
7. VideoLesson validates videoUrl
8. VideoLesson validates duration
9. VideoLesson initializes its own fields
10. Fully constructed object returned

যদি parent validation fail করে:

new VideoLesson(
        -1L,
        "Parent Construction",
        "https://example.com/video",
        15
);

Child initialization পর্যন্ত execution পৌঁছাবে না।

Object creation fail করবে।


Parent Failure Stops Child Construction

Parent:

if (id <= 0) {
    throw new IllegalArgumentException(
            "Content ID must be positive."
    );
}

Child-specific fields তখনো assign হবে না।

Caller কোনো partially created VideoLesson পাবে না।

Constructor exception object creation prevent করে।


Avoid Calling Overridable Methods from Constructors

Dangerous parent constructor:

public ContentItem(
        long id,
        String title
) {
    this.id = id;
    this.title = title;

    validateContent();
}

Suppose validateContent() child override করেছে এবং child field use করে।

@Override
protected void validateContent() {
    if (videoUrl.isBlank()) {
    }
}

Parent constructor execute হওয়ার সময় videoUrl এখনো initialize হয়নি।

Result:

NullPointerException
Unexpected behavior
Partially initialized state access

Practical rule:

Constructor থেকে overridable method call avoid করুন।

Constructor নিজের private বা final helper ব্যবহার করতে পারে।


Safe Constructor Helper

public ContentItem(
        long id,
        String title
) {
    validateId(id);
    validateTitle(title);

    this.id = id;
    this.title = title.strip();
}

private static void validateId(
        long id
) {
}

private static void validateTitle(
        String title
) {
}

Private এবং static helper child override করতে পারে না।

Initialization predictable থাকে।


Common Mistakes

Forgetting the Parent Constructor

public VideoLesson(
        long id,
        String title
) {
}

Parent no-argument constructor না থাকলে compile error।


Adding an Invalid No-Argument Parent Constructor

public ContentItem() {
}

শুধু child compilation সহজ করার জন্য required invariants weaken করা উচিত নয়।


Writing super(...) After Other Statements

super(...) first statement হতে হবে।


Trying to Access Parent Private Fields

this.title =
        title;

Child থেকে parent private field access করা যায় না।


Making Fields Protected for Convenience

protected String title;

Child validation bypass করতে পারে।

Private fields এবং controlled methods prefer করুন।


Assuming Constructors Are Inherited

Parent constructor child automatically পায় না।


Using Both this(...) and super(...)

এক constructor-এ directভাবে দুটো call করা যায় না।


Calling Overridable Methods from Parent Constructor

Child state initialize হওয়ার আগে overridden method execute হতে পারে।


Making Every Method Final

Inheritance extension points হারিয়ে যেতে পারে।

Only invariant-critical behavior final করুন।


Leaving Every Class Open for Extension

Technically extendable class safe inheritance base নাও হতে পারে।


Practice Exercises

Exercise 1: Add QuizLesson

Parent:

ContentItem

Child fields:

questionCount
passingScore

Constructor:

  • super(id, title) call করবে
  • Question count positive validate করবে
  • Passing score 0100 validate করবে

Exercise 2: Predict Constructor Order

Create:

ContentItem
→ VideoLesson
→ LiveVideoLesson

Each constructor একটি message print করবে।

Predict output when:

new LiveVideoLesson(...);

Exercise 3: Fix Missing Parent Constructor Call

Parent:

public ContentItem(
        long id,
        String title
) {
}

Child:

public VideoLesson(
        String videoUrl
) {
    this.videoUrl =
            videoUrl;
}

Refactor child constructor so parent state validভাবে initialize হয়।


Exercise 4: Replace Protected Field

Weak parent:

protected boolean published;

Child direct mutation:

published = true;

Refactor parent to:

  • Keep field private
  • Expose meaningful query
  • Expose controlled publication behavior

Exercise 5: Choose final

Decide whether each should be final:

  1. Immutable CourseCode class
  2. ContentItem.getId()
  3. ContentItem.publish()
  4. Mutable VideoLesson class
  5. Money class

Explain each decision।


Exercise 6: this(...) and super(...)

Create two VideoLesson constructors:

VideoLesson(
        long id,
        String title,
        String videoUrl
)

and:

VideoLesson(
        long id,
        String title,
        String videoUrl,
        int durationInMinutes
)

Shorter constructor default duration 1 দিয়ে complete constructor delegate করবে।


Exercise 7: Find the Constructor Risk

Review:

public ContentItem(
        String title
) {
    this.title =
            title;

    prepare();
}

protected void prepare() {
}

Explain why child override করলে construction unsafe হতে পারে।


Predict the Result

Question 1

public class Parent {

    public Parent() {
        System.out.println(
                "Parent"
        );
    }
}
public class Child
        extends Parent {

    public Child() {
        System.out.println(
                "Child"
        );
    }
}
new Child();

Question 2

Parent:

public Parent(
        int value
) {
}

Child:

public Child() {
}

Will it compile if parent has no no-argument constructor?


Question 3

public class Parent {

    private int value;
}

Can child directভাবে লিখতে পারে?

value = 10;

Question 4

public final class CourseCode {

}

Can another class extend it?


Question 5

public final void publish() {
}

Can a child override publish()?


Predict the Result Answers

Answer 1

Parent
Child

Parent constructor first execute হয়।

Answer 2

না।

Compiler automatic super() call করতে চাইবে, কিন্তু matching parent constructor নেই।

Answer 3

না।

Fieldটি parent class-এর private member।

Answer 4

না।

Final class extend করা যায় না।

Answer 5

না।

Final method override করা যায় না।


Knowledge Check

Question 1

Child object তৈরির সময় parent constructor কেন execute হয়?

Question 2

super(...) কী করে?

Question 3

super(...) constructor body-এর কোথায় থাকতে হয়?

Question 4

Explicit super(...) না থাকলে compiler কী চেষ্টা করে?

Question 5

Parent no-argument constructor না থাকলে কী হতে পারে?

Question 6

Constructors কি inherited হয়?

Question 7

this(...) এবং super(...)-এর difference কী?

Question 8

একই constructor-এ directভাবে দুটো ব্যবহার করা যায় কি?

Question 9

Child কি parent-এর private field direct access করতে পারে?

Question 10

Parent private state child কীভাবে use করতে পারে?

Question 11

Protected field risky কেন?

Question 12

Protected method কখন useful?

Question 13

Final method কী prevent করে?

Question 14

Final class কী prevent করে?

Question 15

Constructor থেকে overridable method call risky কেন?


Knowledge Check Answers

Answer 1

Child object-এর parent portion এবং inherited state validভাবে initialize করতে।

Answer 2

Parent class-এর matching constructor call করে।

Answer 3

First statement হিসেবে।

Answer 4

Automatic super() call add করার চেষ্টা করে।

Answer 5

Explicit matching super(...) না দিলে compile error হবে।

Answer 6

না। Child নিজের constructors declare করে।

Answer 7

this(...) same class-এর অন্য constructor call করে। super(...) parent constructor call করে।

Answer 8

না। দুটোই first statement হতে চায়।

Answer 9

না।

Answer 10

Parent-এর public বা protected methods ব্যবহার করে।

Answer 11

Child direct mutation করে parent invariants bypass করতে পারে এবং implementation coupling বাড়ে।

Answer 12

Parent deliberately subclass customization বা internal collaboration allow করলে।

Answer 13

Child method overriding।

Answer 14

Class inheritance বা subclass creation।

Answer 15

Parent constructor চলার সময় child fields এখনো initialize নাও হতে পারে।


Lesson Summary

এই lesson-এ আমরা শিখেছি:

  • Child object-এর মধ্যে parent state এবং child state থাকে
  • Parent portion child-এর আগে initialize হয়
  • super(...) parent constructor call করে
  • Parent constructor validation child classes reuse করে
  • super(...) first statement হতে হয়
  • Explicit call না থাকলে compiler super() add করার চেষ্টা করে
  • Parent no-argument constructor না থাকলে explicit matching call প্রয়োজন
  • Constructors inherited হয় না
  • Child constructor additional required state initialize করতে পারে
  • this(...) same-class constructor chaining করে
  • super(...) parent construction initiate করে
  • One constructor directভাবে দুটো call করতে পারে না
  • Parent private state child object-এর অংশ, কিন্তু child class direct access করতে পারে না
  • Public এবং protected methods inherited access provide করতে পারে
  • Protected fields encapsulation এবং invariants দুর্বল করতে পারে
  • Private fields with controlled behavior generally safer
  • Protected methods intentional extension points হতে পারে
  • Public parent methods সব child types-এর contract-এর অংশ
  • final method overriding prevent করে
  • final class inheritance prevent করে
  • Every class automatically safe inheritance base নয়
  • Constructor থেকে overridable method call unsafe initialization তৈরি করতে পারে
  • Parent এবং child প্রত্যেকে নিজের state validation-এর দায়িত্ব নেয়

Next Lesson

পরবর্তী lesson:

Method Overriding and Runtime Polymorphism

আমরা শিখব:

  • Method overriding
  • @Override
  • Parent reference এবং child object
  • Runtime method dispatch
  • super.method()
  • Overloading বনাম overriding
  • Static method hiding
  • Fields কেন polymorphic নয়
  • Parent contract preserve করা