Object-Oriented Programming Foundations
The `this` Keyword and Method Overloading
আপনি একটি free preview lesson দেখছেন।
Lesson Overview
Constructor এবং method parameters-এর name অনেক সময় object fields-এর name-এর সঙ্গে same রাখা হয়।
Example:
class Course {
String title;
Course(
String title
) {
title = title;
}
}
Codeটি compile করলেও object field expectedভাবে initialize হবে না।
কারণ constructor parameter title, field title-কে shadow করেছে।
Current object-এর field explicitly refer করতে Java-তে this keyword ব্যবহার করা হয়।
this.title = title;
this আরও ব্যবহার করা যায়:
- Current object refer করতে
- Current object-এর fields এবং methods access করতে
- একটি constructor থেকে অন্য constructor call করতে
- Current object অন্য method-এ pass করতে
এই lesson-এ আমরা method এবং constructor overloading-ও শিখব।
Overloading একই operation-এর meaningful variations support করতে পারে। কিন্তু unnecessary overloads object API confusing করে তুলতে পারে।
Learning Objectives
এই lesson শেষ করার পর আপনি পারবেন:
thisকী represent করে তা ব্যাখ্যা করতে- Field shadowing identify করতে
this.fieldব্যবহার করে field এবং parameter আলাদা করতেthis()দিয়ে constructor chaining করতে- Constructor duplication কমাতে
- Method overloading explain করতে
- Constructor overloading implement করতে
- Compiler কীভাবে overload select করে তা বুঝতে
- Return type alone দিয়ে overload কেন করা যায় না তা ব্যাখ্যা করতে
- Ambiguous এবং unnecessary overload avoid করতে
What Does this Mean?
একটি instance method বা constructor execute হওয়ার সময় this current object-কে refer করে।
Example:
Course javaCourse =
new Course(
"Java and OOP Foundation",
20
);
Constructor execute হওয়ার সময়:
this
javaCourse যে নতুন object-কে refer করবে, সেই current Course object-কে represent করে।
Field Shadowing
একটি local variable বা parameter-এর name field-এর name-এর same হলে field shadowed হয়।
public class Course {
String title;
Course(
String title
) {
title = title;
}
}
Constructor body-এর দুই পাশের title parameter-কে refer করে।
Conceptually:
parameter title = parameter title
Object field unchanged থেকে যায়।
Using this.field
Current object-এর field refer করতে:
this.title
Correct constructor:
public class Course {
String title;
Course(
String title
) {
this.title = title;
}
}
এখানে:
this.title → Current object's field
title → Constructor parameter
Why Same Names Are Common
Alternative parameter name ব্যবহার করা যায়:
Course(
String initialTitle
) {
title =
initialTitle;
}
এটিও correct।
তবে Java code-এ field এবং parameter-এর same name common:
Course(
String title,
int totalLessons
) {
this.title =
title;
this.totalLessons =
totalLessons;
}
এতে public constructor contract এবং object field names consistent থাকে।
A Complete Constructor with this
public class Course {
String title;
int totalLessons;
long priceInPaisa;
Course(
String title,
int totalLessons,
long priceInPaisa
) {
if (
title == null
|| title.isBlank()
) {
throw new IllegalArgumentException(
"Course title is required."
);
}
if (totalLessons <= 0) {
throw new IllegalArgumentException(
"Total lessons must be greater than zero."
);
}
if (priceInPaisa < 0) {
throw new IllegalArgumentException(
"Price cannot be negative."
);
}
this.title =
title.strip();
this.totalLessons =
totalLessons;
this.priceInPaisa =
priceInPaisa;
}
}
this validation-এর জন্য required নয়।
এটি assignment-এর সময় field এবং parameter distinguish করেছে।
this Is Often Optional
যখন naming conflict নেই, this optional।
void publish() {
published = true;
}
এটি একই:
void publish() {
this.published = true;
}
প্রথম version সাধারণত cleaner।
Useful rule:
thisপ্রয়োজন হলে বা meaning clearer করলে ব্যবহার করুন; every field access-এর আগে mechanically ব্যবহার করার দরকার নেই।
Calling Methods with this
Current object-এর method call করতে this ব্যবহার করা যায়।
boolean canPublish() {
return title != null
&& !title.isBlank()
&& totalLessons > 0;
}
void publish() {
if (!this.canPublish()) {
return;
}
published = true;
}
এখানে this optional:
if (!canPublish()) {
return;
}
দুটিই current object-এর method call করে।
Passing the Current Object
কখনো current object অন্য method-এ pass করা যায়।
auditService.recordCourseUpdate(
this
);
এখানে this current Course object।
তবে domain object-এর ভেতরে services pass করা বা external side effects perform করা carefully design করতে হয়।
Beginner level-এ শুধু conceptটি মনে রাখুন:
this = current object reference
this Cannot Be Used in a Static Context
static method কোনো specific object-এর সঙ্গে execute হয় না।
Therefore:
static void displayTitle() {
System.out.println(
this.title
);
}
compile হবে না।
কারণ static context-এ current object নেই।
Static এবং instance members পরবর্তী lesson-এ বিস্তারিত শেখানো হবে।
Constructor Overloading
একটি class-এ multiple constructors থাকতে পারে, যদি তাদের parameter lists different হয়।
Example:
public class Course {
String title;
int totalLessons;
long priceInPaisa;
Course(
String title,
int totalLessons
) {
this.title =
title;
this.totalLessons =
totalLessons;
this.priceInPaisa = 0;
}
Course(
String title,
int totalLessons,
long priceInPaisa
) {
this.title =
title;
this.totalLessons =
totalLessons;
this.priceInPaisa =
priceInPaisa;
}
}
Usage:
Course freeCourse =
new Course(
"Java Fundamentals",
20
);
Course paidCourse =
new Course(
"Backend Development",
30,
799_000L
);
এটিকে constructor overloading বলা হয়।
The Duplication Problem
আগের constructors-এ same assignment logic repeat হয়েছে।
this.title = title;
this.totalLessons = totalLessons;
Validation add করলে duplication আরও বাড়বে।
Duplicate constructor logic risk তৈরি করে:
- Validation এক constructor-এ update হলেও অন্যটিতে না হতে পারে
- Defaults inconsistent হতে পারে
- Maintenance কঠিন হয়
Constructor chaining duplication কমায়।
Calling Another Constructor with this()
একটি constructor থেকে একই class-এর অন্য constructor call করতে:
this(...)
Example:
public class Course {
String title;
int totalLessons;
long priceInPaisa;
Course(
String title,
int totalLessons
) {
this(
title,
totalLessons,
0
);
}
Course(
String title,
int totalLessons,
long priceInPaisa
) {
if (
title == null
|| title.isBlank()
) {
throw new IllegalArgumentException(
"Course title is required."
);
}
if (totalLessons <= 0) {
throw new IllegalArgumentException(
"Total lessons must be greater than zero."
);
}
if (priceInPaisa < 0) {
throw new IllegalArgumentException(
"Price cannot be negative."
);
}
this.title =
title.strip();
this.totalLessons =
totalLessons;
this.priceInPaisa =
priceInPaisa;
}
}
Two-argument constructor:
Course(
String title,
int totalLessons
)
three-argument constructor-কে call করেছে এবং default price দিয়েছে:
0
this() Must Be the First Statement
Constructor chaining call constructor body-এর first statement হতে হবে।
Wrong:
Course(
String title,
int totalLessons
) {
System.out.println(
"Creating course"
);
this(
title,
totalLessons,
0
);
}
Compile হবে না।
Correct:
Course(
String title,
int totalLessons
) {
this(
title,
totalLessons,
0
);
}
Reason:
Java constructor initialization order predictable রাখতে চায়।
Avoid Recursive Constructor Calls
Invalid design:
Course(
String title
) {
this(
title,
0
);
}
Course(
String title,
int totalLessons
) {
this(
title
);
}
প্রতিটি constructor অন্যটিকে call করছে।
এটি recursive constructor invocation এবং compile হবে না।
একটি primary constructor actual initialization করবে।
Other constructors সেটিতে delegate করতে পারে।
Choosing a Primary Constructor
A useful pattern:
- One constructor accepts complete required state
- Shorter constructors provide meaningful defaults
- Validation and assignments remain in the complete constructor
Example:
Course(
String title,
int totalLessons,
long priceInPaisa
)
Primary constructor।
Course(
String title,
int totalLessons
)
Free course তৈরি করার convenience constructor।
Overloaded Constructors Must Represent Meaningful Creation Paths
Overloading শুধু syntax convenience-এর জন্য নয়।
Each constructor should represent a clear valid way to create the object।
Reasonable:
new Course(
"Java Fundamentals",
20
);
Meaning:
Create a free course
Reasonable:
new Course(
"Backend Development",
30,
799_000L
);
Meaning:
Create a paid course
Potentially confusing:
Course(
String title
)
যদি total lesson count required invariant হয়, title-only constructor invalid object তৈরি করতে পারে।
Convenience should not weaken object validity।
Method Overloading
একই class-এ একই method name-এর multiple methods declare করা যায়, যদি parameter lists different হয়।
Example:
void completeLesson() {
completeLessons(1);
}
boolean completeLessons(
int lessonCount
) {
if (lessonCount <= 0) {
return false;
}
int updatedCount =
completedLessons
+ lessonCount;
if (
updatedCount
> totalLessons
) {
return false;
}
completedLessons =
updatedCount;
return true;
}
এখানে method names exact same নয়:
completeLesson
completeLessons
তাই এটি overloading নয়।
Actual overloading:
boolean complete(
int lessonCount
) {
// Complete by count
}
boolean complete(
Lesson lesson
) {
// Complete a specific lesson
}
Same method name:
complete
Different parameter types:
int
Lesson
Valid Method Overloading
Methods overload হতে পারে parameter-এর:
- Number different হলে
- Types different হলে
- Type order different হলে
Different Parameter Count
void changePrice(
long priceInPaisa
) {
}
void changePrice(
long priceInPaisa,
boolean applyImmediately
) {
}
Technically valid।
তবে boolean argument call clarity কমাতে পারে।
Different Parameter Types
void complete(
int lessonCount
) {
}
void complete(
Lesson lesson
) {
}
Different Parameter Order
void register(
String email,
int age
) {
}
void register(
int age,
String email
) {
}
Technically valid, কিন্তু poor design হতে পারে।
Argument order ভুল হওয়ার risk এবং API confusion বাড়ে।
Return Type Alone Cannot Overload a Method
Invalid:
int calculateProgress() {
return 80;
}
double calculateProgress() {
return 80.0;
}
Parameter lists same:
calculateProgress()
calculateProgress()
Compiler method call দেখে কোনটি choose করবে বুঝতে পারবে না।
Caller লিখেছে:
enrollment.calculateProgress();
Return value use না করলে return type থেকে selection অসম্ভব।
Therefore:
Method signature-এর overloading distinction parameters দিয়ে হয়, return type দিয়ে নয়।
Method Signature
Beginner level-এ method signature বলতে সাধারণত বোঝানো হয়:
- Method name
- Parameter types
- Parameter order
Example:
complete(int)
complete(Lesson)
complete(int, boolean)
Return type signature distinction তৈরি করে না।
Parameter names-ও overload distinction তৈরি করে না।
Invalid:
void update(
int completed
) {
}
void update(
int total
) {
}
দুটির signature same:
update(int)
How Java Selects an Overload
Compiler method call-এর arguments দেখে matching method select করে।
Given:
void printValue(
int value
) {
System.out.println(
"int: " + value
);
}
void printValue(
String value
) {
System.out.println(
"String: " + value
);
}
Calls:
printValue(10);
printValue("Nur");
Compiler selects:
10 → printValue(int)
"Nur" → printValue(String)
Numeric Conversion and Overload Selection
Consider:
void show(
int value
) {
}
void show(
long value
) {
}
Call:
show(10);
10 is an int literal, so exact int overload selected হবে।
Call:
show(10L);
long overload selected হবে।
Overload resolution numeric conversions-এর কারণে complex হতে পারে।
Beginner-friendly API-তে overloads clearly distinguishable রাখা ভালো।
Ambiguous Overloads
Consider:
void notifyLearner(
String message
) {
}
void notifyLearner(
EmailTemplate template
) {
}
Call:
notifyLearner(null);
null both reference types-এর সঙ্গে compatible।
Compiler decide করতে নাও পারে কোন overload use হবে।
Result:
Ambiguous method call
This is one reason overloads carefully design করতে হয়।
Autoboxing Can Complicate Overloading
Consider:
void process(
int value
) {
}
void process(
Integer value
) {
}
Calls এবং null values-এর behaviour beginner-এর জন্য confusing হতে পারে।
Unless both overloads have a strong use case, such designs avoid করা ভালো।
Overloading vs Different Method Names
Overloading useful যখন operations conceptually same।
Good candidate:
findById(long id)
findById(String externalId)
But even here method names may be clearer:
findByDatabaseId(long id)
findByExternalId(String externalId)
Different names often communicate domain meaning better।
Ask:
Are these truly the same operation with different input forms, or are they different concepts?
Meaningful Overloading Example
Suppose a course price can be changed using either:
- Exact amount
- Percentage discount
Using same primitive type would be confusing:
changePrice(10);
Does 10 mean:
- 10 paisa?
- 10 taka?
- 10 percent?
Overloading cannot solve semantic ambiguity if types are same।
Clear methods:
changePrice(
long newPriceInPaisa
);
applyDiscountPercentage(
int discountPercentage
);
Different names are stronger।
Constructor Overloading vs Static Factory Methods
Multiple constructors sometimes become hard to understand:
new Course(
"Java",
20,
0
);
What does 0 mean?
A named creation method can be clearer:
Course.freeCourse(
"Java",
20
);
Or:
Course.paidCourse(
"Backend Development",
30,
799_000L
);
These are static factory methods, which will make more sense after learning static members।
For now, remember:
Constructor overloads are useful, but constructors cannot have descriptive names beyond the class name।
A Focused Course Example
Course.java
public class Course {
String title;
int totalLessons;
long priceInPaisa;
boolean published;
Course(
String title,
int totalLessons
) {
this(
title,
totalLessons,
0
);
}
Course(
String title,
int totalLessons,
long priceInPaisa
) {
if (
title == null
|| title.isBlank()
) {
throw new IllegalArgumentException(
"Course title is required."
);
}
if (totalLessons <= 0) {
throw new IllegalArgumentException(
"Total lessons must be greater than zero."
);
}
if (priceInPaisa < 0) {
throw new IllegalArgumentException(
"Price cannot be negative."
);
}
this.title =
title.strip();
this.totalLessons =
totalLessons;
this.priceInPaisa =
priceInPaisa;
}
boolean changeTitle(
String title
) {
if (
title == null
|| title.isBlank()
) {
return false;
}
this.title =
title.strip();
return true;
}
boolean changePrice(
long priceInPaisa
) {
if (priceInPaisa < 0) {
return false;
}
this.priceInPaisa =
priceInPaisa;
return true;
}
boolean canPublish() {
return !title.isBlank()
&& totalLessons > 0;
}
boolean publish() {
if (!canPublish()) {
return false;
}
published = true;
return true;
}
}
Using the Constructors
public class Main {
public static void main(String[] args) {
Course freeCourse =
new Course(
"Java Fundamentals",
20
);
Course paidCourse =
new Course(
"Backend Development",
30,
799_000L
);
paidCourse.changeTitle(
"Backend Development with Spring Boot"
);
paidCourse.publish();
System.out.println(
freeCourse.title
);
System.out.println(
freeCourse.priceInPaisa
);
System.out.println(
paidCourse.title
);
System.out.println(
paidCourse.published
);
}
}
Output:
Java Fundamentals
0
Backend Development with Spring Boot
true
Engineering Note: Avoid Convenience That Hides Meaning
Overloading is convenient, but convenience alone is not enough।
This call is technically simple:
new Course(
"Java",
20
);
Its meaning should be documented or obvious:
A constructor without price creates a free course.
If default meaning is not obvious, a named factory may later be better।
Strong API design prioritizes:
- Clarity
- Validity
- Predictability
over saving a few characters।
Common Mistakes
Writing title = title
Course(
String title
) {
title = title;
}
Parameter assigns to itself।
Correct:
this.title =
title;
Overusing this
void publish() {
this.published = true;
}
Valid, but this is optional here।
published = true;
is simpler।
Using this in Static Methods
static void display() {
System.out.println(
this.title
);
}
Invalid, because static context has no current object।
Placing this() After Another Statement
Course(
String title
) {
validate(title);
this(
title,
10
);
}
Invalid।
this() must be first।
Duplicating Constructor Validation
Multiple constructors each contain same validation logic।
Better:
- One primary constructor
- Other constructors delegate with
this()
Overloading by Return Type Only
int value() {
}
double value() {
}
Invalid because parameter lists are same।
Overloading with Different Parameter Names Only
void update(
int completed
) {
}
void update(
int total
) {
}
Invalid because both signatures are update(int)।
Creating Ambiguous Overloads
Too many related reference-type overloads can make null calls ambiguous।
Using Overloading for Different Concepts
process(int price)
process(String learnerName)
The methods accept different types, but the shared name process expresses no useful domain concept।
Practice Exercises
Exercise 1: Fix Field Shadowing
Correct this constructor:
public class Learner {
String name;
String email;
Learner(
String name,
String email
) {
name = name;
email = email;
}
}
Exercise 2: Constructor Chaining
Create a Course class with:
Course(
String title,
int totalLessons
)
for free courses, and:
Course(
String title,
int totalLessons,
long priceInPaisa
)
for paid courses।
The shorter constructor must delegate to the complete constructor।
Exercise 3: Select the Primary Constructor
For an Enrollment, consider:
learnerName
courseTitle
completedLessons
totalLessons
Decide which constructor should be primary।
Explain which values can have meaningful defaults।
Exercise 4: Identify Overloads
Which method pairs are valid overloads?
Pair A
void update(int value)
void update(long value)
Pair B
int progress()
double progress()
Pair C
void enroll(Learner learner)
void enroll(String learnerEmail)
Pair D
void update(int completed)
void update(int total)
Exercise 5: Improve an Unclear API
Improve:
course.update(10);
course.update(true);
course.update("Java");
Use meaningful method names based on possible intentions।
Exercise 6: Find Ambiguity
Explain why this call may be ambiguous:
notify(null);
Given:
void notify(String message)
void notify(EmailTemplate template)
Exercise 7: Decide Between Overloading and Different Names
Design methods for:
- Changing exact course price
- Applying a discount percentage
Decide whether they should share one overloaded method name or use different names।
Explain your choice।
Predict the Result
Question 1
public class Learner {
String name;
Learner(
String name
) {
name = name;
}
}
Learner nur =
new Learner(
"Nur"
);
System.out.println(
nur.name
);
Question 2
public class Learner {
String name;
Learner(
String name
) {
this.name =
name;
}
}
What will nur.name contain?
Question 3
Given:
void show(
int value
) {
System.out.println(
"int"
);
}
void show(
long value
) {
System.out.println(
"long"
);
}
What will this print?
show(10);
Question 4
Will this compile?
int calculate() {
return 1;
}
double calculate() {
return 1.0;
}
Predict the Result Answers
Answer 1
null
Parameter নিজের কাছেই assign হয়েছে। Field initialize হয়নি।
Answer 2
Nur
this.name current object field refer করেছে।
Answer 3
int
10 একটি int literal, তাই exact int overload select হবে।
Answer 4
না।
Return type alone method overloading support করে না।
Knowledge Check
Question 1
this কী represent করে?
Question 2
Field shadowing কী?
Question 3
this.title = title-এ দুইটি title কী represent করে?
Question 4
this কি সব field access-এর আগে required?
Question 5
this static method-এ ব্যবহার করা যায় না কেন?
Question 6
Constructor overloading কী?
Question 7
this() কী কাজে ব্যবহৃত হয়?
Question 8
this() constructor body-এর কোথায় থাকতে হয়?
Question 9
Constructor chaining-এর benefit কী?
Question 10
Method overloading কী?
Question 11
Return type alone দিয়ে overload করা যায় না কেন?
Question 12
Parameter names different হলে কি overload তৈরি হয়?
Question 13
Ambiguous overload কী?
Question 14
Different method names overloading-এর চেয়ে কখন clearer হতে পারে?
Knowledge Check Answers
Answer 1
Current object reference।
Answer 2
Local variable বা parameter same name ব্যবহার করে field-কে hide করলে।
Answer 3
this.titlecurrent object-এর fieldtitlemethod বা constructor parameter
Answer 4
না। Naming conflict না থাকলে এটি optional।
Answer 5
Static method কোনো specific object-এর সঙ্গে execute হয় না, তাই current object নেই।
Answer 6
Different parameter listsসহ same class-এ multiple constructors declare করা।
Answer 7
একটি constructor থেকে একই class-এর অন্য constructor call করতে।
Answer 8
First statement হিসেবে।
Answer 9
Duplicate validation এবং initialization logic কমায়।
Answer 10
Same method name-এর multiple methods, যাদের parameter lists different।
Answer 11
Method call-এর arguments দেখে compiler method select করে। Same parameters হলে return type selection-এর জন্য যথেষ্ট নয়।
Answer 12
না। Parameter types এবং order same হলে signature same।
Answer 13
যখন compiler supplied arguments-এর জন্য একটি unique overload select করতে পারে না।
Answer 14
যখন operations technically different input নেয়, কিন্তু domain meaning একই নয় বা overload call ambiguous হয়।
Lesson Summary
এই lesson-এ আমরা শিখেছি:
thiscurrent object-কে refer করে- Same-name parameter field-কে shadow করতে পারে
this.fieldobject field এবং parameter distinguish করে- Naming conflict না থাকলে
thisoptional - Static context-এ current object না থাকায়
thisunavailable - Multiple constructors different creation paths support করতে পারে
this()দিয়ে constructor chaining করা যায়this()constructor-এর first statement হতে হয়- One primary constructor validation এবং assignment centralize করতে পারে
- Constructor overloads meaningful valid creation paths represent করা উচিত
- Method overloading same operation-এর input variations support করে
- Parameter count, types, এবং order overload distinguish করতে পারে
- Return type alone overload distinguish করতে পারে না
- Parameter names overload distinction তৈরি করে না
- Too many overloads API confusing করতে পারে
- Ambiguous overloads compiler errors এবং caller confusion তৈরি করে
- Different method names অনেক ক্ষেত্রে domain meaning better express করে
- Convenience-এর চেয়ে clarity এবং validity বেশি গুরুত্বপূর্ণ
Next Lesson
পরবর্তী lesson:
Encapsulation, Access Control, and Object Invariants
আমরা শিখব:
- Why direct field access is dangerous
privatefields- Public object API
- Access modifiers
- Getters and setters
- Why every field should not have a setter
- Protecting object invariants
- Behavior-focused methods
- Keeping objects valid after construction