Java Access Modifiers සිංහලෙන්: Public, Private, Protected, Default | SC Guide

ආයුබෝවන් යාළුවනේ! කොහොමද ඉතින්? අද අපි කතා කරන්න යන්නේ Java Programming වල ගොඩක්ම වැදගත්, හැබැයි සමහර වෙලාවට අලුතින් ඉගෙන ගන්න අයට පොඩ්ඩක් අවුල් වෙන්න පුළුවන් මාතෘකාවක් ගැන – ඒ තමයි Access Modifiers. විශේෂයෙන්ම Public, Private, Protected, Default කියන මේ සිව්දෙනා ගැන තමයි අපි ගැඹුරින්ම බලන්නේ. මේක Java වල විතරක් නෙවෙයි, Object-Oriented Programming (OOP) කරන අයට අත්යවශ්යම Concept එකක්. එහෙනම් වැඩේට බහිමු!
එකලස් කිරීමේ රහස: Encapsulation කියන්නේ මොකක්ද?
ඔන්න ඉස්සෙල්ලම අපි මේ Access Modifiers වලට පදනම දාන Encapsulation ගැන පොඩ්ඩක් කතා කරමු. Encapsulation කියන්නේ මොකක්ද? සරලව කිව්වොත්, අපේ Class එකක් ඇතුළේ තියෙන Data (variables) සහ ඒ Data එක්ක වැඩ කරන Methods එකට එකතු කරලා, ඒ Data වලට පිටින් Access කරන එක පාලනය කරන එකට. හරියට කැප්සියුලයක් වගේ. කැප්සියුලයක් ඇතුළේ බෙහෙත් තියෙනවා, හැබැයි අපිට ඒක කඩලා ඇතුළේ තියෙන බෙහෙත් කන්න බෑ, සම්පූර්ණ කැප්සියුල එකම තමයි ගිලින්න ඕනේ. ඒ වගේම තමයි අපේ Object එකේ ඇතුළේ තියෙන දේවල් පාලනය කරන එක තමයි Encapsulation වලින් වෙන්නේ.
මේකෙන් වෙන්නේ මොකක්ද? අපේ Code එකේ ආරක්ෂාව (Security) වැඩි වෙනවා, නිකරුණේ Data වෙනස් වීම් නවතිනවා, Code එක Maintain කරන්න පහසු වෙනවා. මොකද Class එකක Internal Data පිටස්තර Class වලට සෘජුවම Access කරන්න නොදී, Methods හරහා පමණක් Access කරන්න අවස්ථාව දීම නිසා, Data එකේ Integrity එක ආරක්ෂා වෙනවා. දැන් බලමු මේක කරන්න Access Modifiers කොහොමද උදව් වෙන්නේ කියලා.
1. Public: හැමෝටම පේන විදියට
පළවෙනියටම අපි කතා කරන්නේ Public
ගැන. මේක තමයි Access Modifiers අතරින් ලේසිම එක. Public
කියලා අපි යමක් Declare කළොත්, ඒක ඕනෙම Class එකකට, ඕනෙම Package එකකට Access කරන්න පුළුවන්. හරියට පාරේ යන බස් එකක් වගේ. ඕනෙම කෙනෙකුට ඒක බලන්නත්, පදින්නත් පුළුවන්. ඒ කියන්නේ Public
Members (Variables, Methods, Constructors, Inner Classes) වලට කිසිම Access restriction එකක් නැහැ.
Public භාවිතය
අපි හිතමු අපිට Car
කියලා Class එකක් තියෙනවා කියලා. ඒකේ model
එක, start()
method එක public
කරලා තියෙනවා කියලා.
class Car {
public String model; // Public variable
public void start() { // Public method
System.out.println("Car started!");
}
}
public class Main {
public static void main(String[] args) {
Car myCar = new Car();
myCar.model = "Toyota Prius"; // Public නිසා direct access කරන්න පුළුවන්
myCar.start(); // Public නිසා direct call කරන්න පුළුවන්
System.out.println("My car model is: " + myCar.model);
}
}
උඩ තියෙන Code එකේ model
variable එකයි, start()
method එකයි දෙකම public
නිසා, Main
Class එක ඇතුළේදී අපිට myCar.model
කියලා ඒකට කෙලින්ම Access කරන්නත්, myCar.start()
කියලා method එක Call කරන්නත් පුළුවන්. මේකෙන් වෙන්නේ ඕනෙම තැනකින් ඕනෙම කෙනෙකුට මේවා වෙනස් කරන්නත්, පාවිච්චි කරන්නත් පුළුවන් වීම. හැබැයි මේකෙන් Data Security එකට හානි වෙන්න පුළුවන්. ඒ නිසා Variables හැමවෙලේම Public නොකර ඉන්න එක හොඳයි.
2. Private: මගේ දේවල් මට විතරයි!
දෙවෙනියට එන්නේ Private
. මේක තමයි Public
එකේ සම්පූර්ණ විරුද්ධ පැත්ත. Private
කියලා යමක් Declare කළොත්, ඒක Access කරන්න පුළුවන් වෙන්නේ ඒක Declare කරපු Class එක ඇතුළට විතරයි. ඒ කියන්නේ වෙනත් කිසිම Class එකකට (Subclass එකකටවත්) ඒ Private Members වලට කෙලින්ම Access කරන්න බෑ. හරියට අපේ ගෙදර ඇතුළේ තියෙන අපේ පෞද්ගලික කාමරයක් වගේ. ඒක ඇතුළට යන්න පුළුවන් අපිට විතරයි, නැත්නම් අපේ අවසරය තියෙන අයට විතරයි.
Private භාවිතය සහ Getters/Setters
ඇයි මේ Private
පාවිච්චි කරන්නේ? මේක තමයි Encapsulation වල ප්රධානම අංගය. අපි Class එකක Data hide කරනවා. එහෙම Data hide කරලා, ඒ Data වලට පිටතින් Access කරන්න ඕන නම්, අපි public
Methods හදනවා, ඒවට කියනවා Getters (අගය ගන්න) සහ Setters (අගය සකසන්න) කියලා. මේ Methods හරහා අපිට Data වලට Access කරන එක පාලනය කරන්න පුළුවන්, අවශ්ය Validations දාන්න පුළුවන්.
class BankAccount {
private double balance; // Private variable
public BankAccount(double initialBalance) {
if (initialBalance >= 0) {
this.balance = initialBalance;
} else {
this.balance = 0; // Negative balance allow කරන්නේ නෑ
}
}
// Getter method
public double getBalance() {
return balance;
}
// Setter method (with validation)
public void deposit(double amount) {
if (amount > 0) {
this.balance += amount;
System.out.println("Deposited: " + amount + ". New balance: " + this.balance);
} else {
System.out.println("Deposit amount must be positive.");
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= this.balance) {
this.balance -= amount;
System.out.println("Withdrew: " + amount + ". New balance: " + this.balance);
} else {
System.out.println("Invalid withdrawal amount or insufficient balance.");
}
}
}
public class Main {
public static void main(String[] args) {
BankAccount myAccount = new BankAccount(1000);
// myAccount.balance = 5000; // Compile-time error! Private variable cannot be accessed directly
System.out.println("Current balance: " + myAccount.getBalance()); // Access via getter
myAccount.deposit(200);
myAccount.withdraw(500);
myAccount.withdraw(1000); // Invalid withdrawal attempt
myAccount.deposit(-50); // Invalid deposit attempt
System.out.println("Final balance: " + myAccount.getBalance());
}
}
මේ BankAccount
Class එකේ balance
variable එක private
නිසා, Main
Class එකෙන් ඒකට කෙලින්ම Access කරන්න බෑ. ඒත් අපි getBalance()
, deposit()
, withdraw()
වගේ public
methods හරහා balance
එකට Access කරන්න අවස්ථාව දීලා තියෙනවා. මේකෙන් වෙන්නේ අපේ balance
එක සෘණ වෙන්න දෙන්නේ නැති වගේ Validations දාන්න පුළුවන් වීම. මේක තමයි හොඳම පුරුද්ද.
3. Protected: පවුලේ අයයි, කිට්ටු යාළුවොයි විතරයි
Protected
කියන්නේ Private
සහ Public
අතරමැදි ස්වභාවයක් තියෙන එකක්. Protected
කියලා Declare කරපු Member කෙනෙක්ව Access කරන්න පුළුවන් වෙන්නේ ඒ Member එක Declare කරපු Class එක ඇතුළෙදිමයි, එහෙමත් නැත්නම් ඒ Class එක Extend කරන Subclass වලටයි, ඒ වගේම එකම Package එකේ තියෙන අනිත් Class වලටයි විතරයි. හරියට අපේ පවුලේ අයයි, කිට්ටු යාළුවොයි විතරක් යන Party එකක් වගේ.
Protected භාවිතය: Inheritance (උරුමය) සමඟ
මේක ගොඩක්ම පාවිච්චි වෙන්නේ Inheritance (උරුමය) එක්ක තමයි. Parent Class එකක තියෙන දේවල් Child Class එකකට Access කරන්න දෙන්න ඕන නම්, හැබැයි ඒක පිටින් ඉන්න අයට (වෙනත් Package එකක, Subclass නොවන Class වලට) පේන්න දෙන්න ඕන නැත්නම්, Protected
පාවිච්චි කරනවා.
// Package: com.mycompany.vehicles
package com.mycompany.vehicles;
public class Vehicle { // Class is public so it can be imported by other packages
protected String brand = "Default Brand"; // Protected variable
protected void honk() { // Protected method
System.out.println("Tuut, tuut!");
}
}
// Package: com.mycompany.vehicles (same package as Vehicle)
package com.mycompany.vehicles;
class Car extends Vehicle { // Car is in the same package and extends Vehicle
private String modelName;
public Car(String modelName) {
this.modelName = modelName;
}
public void displayDetails() {
System.out.println("Brand: " + brand); // OK: Accessing protected variable in subclass (same package)
honk(); // OK: Accessing protected method in subclass (same package)
}
}
// Different package: com.mycompany.app
package com.mycompany.app;
import com.mycompany.vehicles.Vehicle; // OK: Vehicle class is public
class Truck extends Vehicle { // Truck is in a different package but extends Vehicle
public void printBrand() {
System.out.println("Truck brand: " + brand); // OK: Accessing protected variable in subclass (different package)
}
public void activateHorn() {
honk(); // OK: Accessing protected method in subclass (different package)
}
}
public class Main {
public static void main(String[] args) {
// Example 1: Same package access (from Car class - though Main is in different package, Car's internal access works)
com.mycompany.vehicles.Car myCar = new com.mycompany.vehicles.Car("Ford Focus");
myCar.displayDetails();
// Example 2: Different package, subclass access (from Truck class)
Truck myTruck = new Truck();
myTruck.printBrand();
myTruck.activateHorn();
// Example 3: Different package, non-subclass direct access (not allowed)
Vehicle someVehicle = new Vehicle(); // OK: Vehicle class is public, so object can be created
// someVehicle.brand = "Another Brand"; // Compile-time error! Cannot access protected directly from non-subclass in different package
// someVehicle.honk(); // Compile-time error! Cannot access protected directly from non-subclass in different package
System.out.println("\n--- Main Class එකට Protected Members වලට කෙලින්ම Access කරන්න බෑ --- ");
System.out.println(" 'someVehicle.brand' සහ 'someVehicle.honk()' කියන Lines Compile-time errors ඇති කරයි.");
}
}
මේ උදාහරණයේදී Vehicle
Class එකේ brand
එකයි, honk()
method එකයි දෙකම protected
. Vehicle
Class එක public
නිසා වෙනත් Package වලට එය import කරන්න පුළුවන්.
Car
Class එකVehicle
එකේ Subclass එකක්. ඒ වගේමCar
Class එකයිVehicle
Class එකයි දෙකම එකම Package එකේ (com.mycompany.vehicles
) තියෙන නිසාbrand
එකටයිhonk()
method එකටයි පහසුවෙන් Access කරන්න පුළුවන්.Truck
Class එකVehicle
එකේ Subclass එකක්. හැබැයිTruck
Class එක වෙනත් Package එකක (com.mycompany.app
) තියෙන්නේ. එහෙම වුණත්,Truck
Class එකVehicle
එක Extend කරන නිසා,protected
member වලට Access කරන්න පුළුවන්.- හැබැයි,
Main
Class එකේදීVehicle
Object එකක් හදලා ඒකේprotected
members වලට කෙලින්ම Access කරන්න බෑ, මොකදMain
Class එකVehicle
එකේ Subclass එකක් නොවන නිසා සහ වෙනත් Package එකක තියෙන නිසා.
4. Default (Package-Private): කවුරුත් කිව්වේ නැත්නම් මොකද වෙන්නේ?
මේකට කියන්නේ Default Access Modifier කියලා. මේක අපි විශේෂයෙන්ම Keyword එකක් දාලා Declare කරන්නේ නෑ. අපි කිසිම Access Modifier එකක් දැම්මේ නැත්නම්, Java Compiler එක විසින් ඒකට Default Access Modifier එක දානවා. මේක Package-Private කියලත් හඳුන්වනවා.
Default Access Modifier භාවිතය
Default Access Modifier එකෙන් කියන්නේ, ඒ Member කෙනෙක්ව Access කරන්න පුළුවන් වෙන්නේ ඒක Declare කරපු Class එක ඇතුළට විතරයි, නැත්නම් ඒක තියෙන Package එකේ තියෙන අනිත් Class වලට විතරයි. Package එකෙන් පිටත Class වලට Access කරන්න බෑ. හරියට අපේ ගමේ යාළුවෝ ටික විතරක් යන Trip එකක් වගේ. ගමේ අය විතරයි එතැනට එන්නේ.
// Package: com.mycompany.core
package com.mycompany.core;
// No access modifier means default (package-private) for the class itself
class DataProcessor {
String internalData = "Secret Information"; // Default (Package-private)
void process() { // Default (Package-private) method
System.out.println("Processing: " + internalData);
}
}
// In the same package as DataProcessor
package com.mycompany.core;
class Utility { // Also default access
void useProcessor() {
DataProcessor processor = new DataProcessor(); // OK: DataProcessor is in the same package
System.out.println("Accessing from same package: " + processor.internalData); // OK: Same package
processor.process(); // OK: Same package
}
}
// Package: com.mycompany.app (Different package)
package com.mycompany.app;
// import com.mycompany.core.DataProcessor; // Compile-time error! Cannot import default class from different package
// import com.mycompany.core.Utility; // Compile-time error! Cannot import default class from different package
public class Main {
public static void main(String[] args) {
System.out.println("\n--- Default Class/Members වෙනත් Package එකක සිට Access කිරීම --- ");
// DataProcessor processor = new DataProcessor();
// උඩින් තියෙන Line එක Compile-time error එකක් ඇති කරයි. මොකද DataProcessor Class එක Default
// Access Modifier එකකින් තියෙන්නේ. ඒ නිසා වෙනත් Package එකකට මේක Access කරන්න බෑ.
System.out.println("DataProcessor class එක Default Access නිසා, වෙනත් Package එකකින් Object හදන්න බැහැ.");
System.out.println("DataProcessor class එක public වුණත්, එහි 'internalData' සහ 'process()' (Default) Members වෙනත් Package එකකට Access කරන්න බැහැ.");
// com.mycompany.core.Utility utility = new com.mycompany.core.Utility();
// Utility Class එකත් Default Access නිසා, මේකත් Compile-time error එකක් ඇති කරයි.
System.out.println("ඒ වගේම, Utility Class එකත් Default Access නිසා, එයත් මේ Package එකෙන් සෘජුව භාවිතා කරන්න බැහැ.");
}
}
මේ උදාහරණයේදී, DataProcessor
Class එකම Default Access Modifier එකෙන් තියෙන්නේ. ඒ නිසා com.mycompany.app
කියන වෙනත් Package එකක තියෙන Main
Class එකට DataProcessor
Class එක import
කරන්නවත්, එහි Object එකක් හදන්නවත් බෑ.
Utility
Class එක DataProcessor
Class එකත් එක්ක එකම Package එකේ (com.mycompany.core
) තියෙන නිසා, ඒවට Access කරන්න පුළුවන්. ඒ වගේම Utility
Class එකත් Default Access එකක් තියෙන නිසා, එයත් com.mycompany.app
Package එකෙන් Access කරන්න බෑ.
මතක තියාගන්න, Class එකකට Default Access Modifier එකක් තියෙනවා නම්, ඒක Package එකෙන් පිටතදී import
කරන්නවත්, Object හදන්නවත් බෑ.
ප්රයෝගික උපදෙස් සහ හොඳම පුරුදු (Best Practices)
Access Modifiers හරියට පාවිච්චි කරන එක ඔබේ Code එකේ Quality එකට ගොඩක් වැදගත්. මෙන්න ඒ සඳහා උපදෙස් කීපයක්:
- Data Hiding (තොරතුරු සැඟවීම): හැමවෙලේම Variables
private
කරන්න පුරුදු වෙන්න. ඒක තමයි Encapsulation වලට ගොඩක්ම උදව් වෙන්නේ. මේකෙන් Data corruption වෙන එක නවත්වන්න පුළුවන්. - Getters/Setters පාවිච්චිය:
private
Variables වලට Access කරන්න ඕන නම්,public
Getters සහ Setters පාවිච්චි කරන්න. මේකෙන් Data Validations දාන්න පුළුවන්කම ලැබෙනවා. - Methods: Class එකක Core functionality එක පෙන්වන Methods
public
කරන්න. හැබැයි Helper Methods (අනිත් Methods වලට උදව් කරන, නමුත් පිටතින් Direct Call කරන්න අවශ්ය නැති Methods) නම්private
හෝprotected
කරන්න. - Default Access Modifier ගැන සැලකිලිමත් වීම: ඔබ විශේෂයෙන්ම කිසිම Modifier එකක් නොදාන අවස්ථා වලදී Default Access Modifier එක ක්රියාත්මක වෙන බව මතක තියාගන්න. සමහර වෙලාවට මේකෙන් unexpected behaviour ඇති වෙන්න පුළුවන්, විශේෂයෙන්ම Class, Interface හෝ Enum එකක් Declare කරන විට.
- Protected: උරුමය සඳහා පමණයි:
protected
පාවිච්චි කරන්න ඕන නම්, ඒක Inheritance එක්ක විතරක් පාවිච්චි කරන්න. ඒ කියන්නේ Subclasses වලට Parent Class එකේ දේවල් Access කරන්න දෙන්න ඕන නම් විතරයි. අනවශ්ය විදියටprotected
පාවිච්චි නොකර ඉන්න. - සරලව සිතීම: Access Modifiers තෝරගන්නකොට, හැමවෙලේම අවම Access Level එක පාවිච්චි කරන්න බලන්න. ඒ කියන්නේ
private
වලින් පටන් අරන්, අවශ්ය නම් විතරක්default
,protected
,public
වලට යන්න.
නිගමනය
ඉතින් යාළුවනේ, මේ තමයි Java වල Access Modifiers ගැන සරලව කිව්වොත් තොරතුරු ටික. මේවා Java Programming වලදී අත්යවශ්ය මූලික සංකල්ප. Encapsulation කියන Object-Oriented Programming (OOP) Concept එක තේරුම් ගන්නත්, හොඳ Design Patterns පාවිච්චි කරන්නත් මේ Access Modifiers ගැන හොඳ අවබෝධයක් තියෙන්න ඕනේ. මේවා පාවිච්චි කරලා, ඔයාලට පුළුවන් Cleaner, Safer, සහ Maintain කරන්න පහසු Code ලියන්න.
මේවා තියරියට විතරක් තේරුම් ගත්තට මදි, අනිවාර්යයෙන්ම මේ Code Examples ඔයාලගේ IDE (IntelliJ, Eclipse, VS Code වගේ) එකේ Run කරලා බලන්න. ඒ වගේම විවිධ Access Modifiers දාලා මොකද වෙන්නේ කියලා Experiment කරන්න. ඔයාලගේ අදහස්, ප්රශ්න පහළින් Comment කරන්න. තව මොනවා ගැනද දැනගන්න කැමති කියලත් කියන්න. එහෙනම් තවත් අලුත් Topic එකකින් හමුවෙමු! Happy Coding!