Access Modifiers (ဘယ်ကနေ သုံးခွင့်ရလဲ သတ်မှတ်တဲ့ keyword များ)
B3.1: Use access modifiers to control visibility of class members.
မြန်မာလို: class member (class ထဲမှာ ပါတဲ့ attribute နဲ့ method) တွေကို ဘယ်ကနေ မြင်ရ၊ သုံးရလဲ (visibility) ဆိုတာကို ထိန်းချုပ်ဖို့ access modifier တွေကို သုံးနိုင်ရပါမယ်။
အဓိက အယူအဆများ
Access Modifier ဆိုတာ ဘာလဲ
Access modifier တွေက class (object တွေ ဖန်တီးဖို့ ပုံစံခွက်) တစ်ခုရဲ့ attribute (object ရဲ့ ဒေတာကို သိမ်းတဲ့ variable) နဲ့ method (သီးခြား အလုပ်တစ်ခု လုပ်ပေးတဲ့ code အပိုင်း) တွေကို program ရဲ့ ဘယ်အပိုင်းတွေက မြင်ပြီး သုံးလို့ရလဲ ဆိုတာကို ထိန်းချုပ်ပေးတဲ့ keyword (programming language မှာ အထူး အဓိပ္ပာယ်ရှိတဲ့ စကားလုံး) တွေပါ။ Encapsulation (ဒေတာနဲ့ method ကို တစ်စုတည်း ထုပ်ပိုးခြင်း) ကို ဖြစ်နိုင်အောင် လုပ်ပေးတဲ့ နည်းလမ်းက သူတို့ပါပဲ: သူတို့ မရှိရင် ဘယ် code မဆို ဘယ်ဒေတာကိုမဆို သုံးလို့ ရနေမှာပါ။
Java မှာ သိထားရမယ့် access modifier သုံးမျိုး ရှိပါတယ်:
| Modifier | ဘယ်သူ သုံးခွင့် ရလဲ | ဘာအတွက် သုံးလဲ |
|---|---|---|
private | Class တစ်ခုတည်းရဲ့ အထဲက code ပဲ | Attribute တွေ (အမြဲလိုလို)၊ helper method (တခြား method တွေကို ကူညီပေးတဲ့ class အတွင်းသုံး method) တွေ |
public | ဘယ် class ထဲက code မဆို | Constructor (object ဖန်တီးချိန် attribute တွေကို စတင် သတ်မှတ်ပေးတဲ့ method)၊ getter (private attribute ရဲ့ တန်ဖိုးကို ပြန်ပေးတဲ့ method)၊ setter (private attribute ရဲ့ တန်ဖိုးကို ပြောင်းတဲ့ method)၊ API method (တခြား code သုံးဖို့ ဖွင့်ပေးထားတဲ့ method) တွေ |
protected | Class တစ်ခုတည်း ထဲက code နဲ့ သူ့ရဲ့ subclass (အမွေဆက်ခံတဲ့ child class) တွေထဲက code (Java မှာဆိုရင် package (ဆက်စပ်တဲ့ class တွေကို စုထားတဲ့ အုပ်စု) တစ်ခုတည်းထဲက တခြား class တွေလည်း ပါပါတယ်) | Subclass တွေ လိုအပ်ပေမယ့် အပြင်က code မထိသင့်တဲ့ attribute ဒါမှမဟုတ် method တွေ |
စတုတ္ထ အဆင့် တစ်ခုလည်း ရှိပါသေးတယ်: default (keyword မရေးထားတဲ့ အဆင့်) ပါ။ Package တစ်ခုတည်းထဲက ဘယ် class ကမဆို သုံးခွင့် ရပါတယ်။ IB Computer Science (နိုင်ငံတကာ ကျောင်းတွေမှာ သင်တဲ့ ကွန်ပျူတာသိပ္ပံ သင်ရိုး) က ဒါကို စာမေးပွဲမှာ မစစ်ပါဘူး၊ ဒါပေမယ့် တကယ့် Java code တွေမှာ တွေ့ရနိုင်ပါတယ်။
(Python မှာ access modifier keyword လုံးဝ မရှိပါဘူး။ IB ရဲ့ Python ရေးထုံးမှာ _name လို နာမည်ရှေ့က underscore (_) တစ်ခုက attribute ဒါမှမဟုတ် method ကို private လို့ ပြပါတယ်၊ underscore မပါတဲ့ နာမည်တွေက public ပါ။)
စံ စည်းမျဉ်းများ
IB အတွက်ရော၊ လုပ်ငန်းခွင်မှာ Java နဲ့ software ရေးတဲ့အခါပါ ဒီ စည်းမျဉ်းတွေကို လိုက်နာပါ:
Attribute တွေ: အမြဲလိုလို private
private String name;
private double height;
private int age;
# Python has no private keyword - the leading underscore marks
# the attribute as private by convention (the form IB uses)
def __init__(self, name, height, age):
self._name = name
self._height = height
self._age = age
Attribute တွေကို private လုပ်ထားရင် အပြင်က ဘယ် code ကမှ ကိုယ့် method တွေကို မဖြတ်ဘဲ သူတို့ကို ဖတ်လို့၊ ပြောင်းလို့ မရတော့ပါဘူး။ ဒါက encapsulation ရဲ့ အခြေခံ အုတ်မြစ်ပါ။
Constructor နဲ့ public method တွေ: public
public Recipe(String name, int servings) { ... }
public int getServings() { ... }
public void setServings(int servings) { ... }
# No leading underscore = public by convention
def __init__(self, name, servings):
# code missing
def get_servings(self):
# code missing
def set_servings(self, servings):
# code missing
ဒါတွေက class ရဲ့ public interface (အပြင်က code သုံးဖို့ ဖွင့်ပေးထားတဲ့ public method တွေ) ဖြစ်ပါတယ်: တခြား class တွေက ကိုယ့် object (class တစ်ခုကနေ ဖန်တီးထားတဲ့ instance) တွေနဲ့ ဆက်သွယ် ကိုင်တွယ်တဲ့ နည်းလမ်းပါ။
Helper method တွေ: private
private boolean isValidAmount(double amount) {
return amount > 0;
}
def _is_valid_amount(self, amount): # leading underscore = private helper
return amount > 0
Helper method တွေက public method တွေကို ကူညီပေးတဲ့ class အတွင်းသုံး tool တွေပါ။ တခြား class တွေ တိုက်ရိုက် မခေါ်သင့်တဲ့ implementation (တကယ် အလုပ်လုပ်အောင် ရေးထားတဲ့ code) အသေးစိတ်တွေပါ။
Access modifier (access specifier လို့လည်း ခေါ်ပါတယ်) က class member တစ်ခုကို ဘယ်ကနေ မြင်ရ၊ သုံးရလဲ (visibility) ဆိုတာ သတ်မှတ်ပါတယ်။
privatemember ကို သူ့ class ကိုယ်တိုင်ရဲ့ အထဲမှာပဲ သုံးလို့ ရပါတယ်။
ဘာကြောင့် အားလုံးကို public မလုပ်တာလဲ
အားလုံး public ဖြစ်နေရင် ဘယ်နေရာက code မဆို ဒါတွေကို လုပ်လို့ ရပါတယ်:
// With public fields -- dangerous
recipe.servings = -999999; // no validation
recipe.name = ""; // empty name
recipe.servings = recipe.servings * 1000; // arbitrary modification
# With public attributes - dangerous
recipe.servings = -999999 # no validation
recipe.name = "" # empty name
recipe.servings = recipe.servings * 1000 # arbitrary modification
private field (object ထဲက အချက်အလက် အကွက်) တွေနဲ့ public method တွေ သုံးရင်:
// With private fields -- safe
recipe.setServings(-999999); // rejected by validation
recipe.setName(""); // rejected by validation
// recipe.servings = ... // compile error -- cannot access private field
# With private (underscored) attributes - safer
recipe.set_servings(-999999) # rejected by validation
recipe.set_name("") # rejected by validation
# recipe._servings = ... # would actually RUN in Python - the underscore is
# # a convention, not enforced; Java refuses to compile
ဒီ ကာကွယ်မှုကို compiler (code တစ်ခုလုံးကို ကြိုတင် ဘာသာပြန်တဲ့ program) ကိုယ်တိုင်က အတင်းအကျပ် လိုက်နာစေပါတယ်။ Class ရဲ့ အပြင်ကနေ private field ကို သုံးတဲ့ code က compile မဖြစ်ပါဘူး။ (Python မှာတော့ မတူပါဘူး: အပြင်က code က _servings ကို ထိတာကို ဘာမှ မတားပါဘူး။ Underscore က သော့ခတ်ထားတာ မဟုတ်ဘဲ ကတိ တစ်ခုသာ ဖြစ်လို့ underscore ပါတဲ့ attribute တွေကို private လိုပဲ သဘောထားပြီး ဆက်ဆံပါ။)
protected: Inheritance (parent class ကနေ အမွေဆက်ခံခြင်း) အတွက်
protected က private နဲ့ public ကြားမှာ ရှိပါတယ်။ protected member ကို class ကိုယ်တိုင်ရဲ့ အထဲမှာရော၊ အဲဒီ class ကို extend လုပ်တဲ့ (အမွေဆက်ခံတဲ့) ဘယ် class (subclass) ထဲမှာမဆိုပါ သုံးလို့ ရပါတယ်။ တခြား package တွေထဲက မဆိုင်တဲ့ class တွေကတော့ မသုံးနိုင်ပါဘူး။
Java မှာ သိထားရမယ့် အသေးစိတ် တစ်ခု ရှိပါတယ်: protected က package တစ်ခုတည်းထဲက ဘယ် class ကိုမဆို (ဆက်စပ်မှု ရှိသည်ဖြစ်စေ၊ မရှိသည်ဖြစ်စေ) သုံးခွင့် ပေးပါတယ်။ Class အားလုံး default package ထဲမှာ ရှိနေတဲ့ project အသေးလေး တစ်ခုမှာဆိုရင် မဆိုင်တဲ့ class တစ်ခုကတောင် protected field ကို ဖတ်လို့ ရနေပြီး compiler က ဘာမှ မပြောပါဘူး။ ဒါကြောင့် protected ကို “subclass တွေအတွက်” လို့ သဘောထားပြီး design လုပ်ပါ၊ တခြား class တွေ မထိစေချင်တဲ့အခါ private နဲ့ getter ကို သုံးပါ။
public class Animal {
protected String name; // subclasses can access directly
private int internalId; // only Animal can access
public Animal(String name) {
this.name = name;
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
System.out.println(this.name); // OK -- protected, Dog is a subclass
// System.out.println(this.internalId); // ERROR -- private, even subclasses can't access
}
}
class Animal():
def __init__(self, name):
self._name = name # Python has no protected keyword either -
self._internal_id = 0 # the same underscore convention covers both
class Dog(Animal):
def __init__(self, name):
Animal.__init__(self, name) # call the parent constructor (Java's super)
print(self._name) # works - subclasses can reach _name
# Python does not enforce any of these levels; by convention a subclass
# may use the parent's underscored attributes, unrelated code should not
protectedကို လိုမှသာ နည်းနည်း သုံးပါ။ အခြေအနေ အများစုမှာprivateနဲ့publicgetter ကို တွဲသုံးတာ ပိုကောင်းပါတယ်၊ ဘာလို့လဲဆိုတော့ ဒေတာကို ဘယ်လို သုံးခွင့်ပေးမလဲဆိုတာကို parent class က အပြည့်အဝ ထိန်းချုပ်နိုင်လို့ပါ။protectedက subclass တွေကို တိုက်ရိုက် သုံးခွင့် ပေးတာကြောင့် tight coupling (class တွေ အချင်းချင်း အရမ်း မှီခိုနေခြင်း) ဖြစ်လာနိုင်ပါတယ်။
Access modifier အနှစ်ချုပ် ပုံ
Same class Subclass Other classes
private ──► ✓ ✗ ✗
protected ──► ✓ ✓ ✗
public ──► ✓ ✓ ✓
ပုံထဲက Same class က class တစ်ခုတည်း၊ Subclass က အမွေဆက်ခံတဲ့ child class၊ Other classes က တခြား class တွေကို ဆိုလိုပါတယ်။ ✓ က သုံးခွင့် ရတယ်၊ ✗ က သုံးခွင့် မရဘူးလို့ ဆိုလိုပါတယ်။
အဖြစ်များတဲ့ အမှားများ
အမှား 1: ပျင်းလို့ attribute တွေကို public လုပ်ထားခြင်း
public int age; // BAD -- no validation, no control
self.age = age # BAD - no underscore makes it public: no validation, no control
ပြင်နည်း: validation (တန်ဖိုး မှန်မမှန် စစ်ခြင်း) ပါတဲ့ setter နဲ့အတူ private int age; လို့ ရေးပါ။ (Python: validation ပါတဲ့ setter နဲ့အတူ self._age။)
အမှား 2: တခြား class တွေ လိုအပ်တဲ့ method တွေ အပါအဝင် အားလုံးကို private လုပ်ထားခြင်း
private int getServings() { ... } // BAD -- other classes can't read the servings
def _get_servings(self): # BAD - the underscore signals "internal only",
return self._servings # but other classes need to read the servings
ပြင်နည်း: getter နဲ့ setter တွေက public ဖြစ်ရပါမယ်။ (Python: getter ကို ရှေ့မှာ underscore မပါဘဲ get_servings လို့ နာမည်ပေးပါ။)
အမှား 3: private နဲ့ protected ကို ရောထွေးခြင်း
private က class တစ်ခုတည်း သာ လို့ ဆိုလိုပါတယ်။ protected က class တစ်ခုတည်း နဲ့ subclass တွေလို့ ဆိုလိုပါတယ်။ Subclass က parent ရဲ့ field ကို တိုက်ရိုက် သုံးဖို့ လိုရင် protected ကို သုံးပါ၊ ဒါပေမယ့် ဖြစ်နိုင်ရင် private နဲ့ getter ကို ပိုရွေးပါ။
အဆင့်ဆင့် ရှင်းပြထားတဲ့ ဥပမာများ
ဥပမာ 1: မှန်ကန်တဲ့ modifier ကို ရွေးခြင်း
Member တစ်ခုစီအတွက် သင့်တော်တဲ့ access modifier ကို ဆုံးဖြတ်ပြီး ဘာကြောင့်လဲ ရှင်းပြပါ:
| Class | Member | Modifier | အကြောင်းရင်း |
|---|---|---|---|
Student | name (attribute) | private | ဒေတာကို ဖုံးထားသင့်ပါတယ်၊ getter ကနေ သုံးပါ |
Student | getName() | public | တခြား class တွေက နာမည်ကို ဖတ်ဖို့ လိုပါတယ် |
Student | setGrade(int) | public | တခြား class တွေက grade (အမှတ်) ကို ပြောင်းဖို့ လိုပါတယ် (validation နဲ့) |
Student | validateGrade(int) | private | Class အတွင်းသုံး helper ပါ၊ အပြင်က code က ဒါကို တိုက်ရိုက် ခေါ်ဖို့ အကြောင်း မရှိပါဘူး |
Animal | sound (Dog, Cat subclass တွေ သုံးတဲ့ attribute) | protected | Subclass တွေက တိုက်ရိုက် သုံးဖို့ လိုပါတယ်၊ အပြင်က class တွေက မလိုပါဘူး |
Recipe | Recipe(String, int) | public | တခြား class တွေက Recipe object တွေကို ဖန်တီးဖို့ လိုပါတယ် |
ဥပမာ 2: Compile error (compile လုပ်ချိန်မှာ ဖြစ်တဲ့ error) ကို ခွဲခြမ်းစိတ်ဖြာခြင်း
public class Secret {
private int code = 42;
public int getCode() { return code; }
}
public class Main {
public static void main(String[] args) {
Secret s = new Secret();
System.out.println(s.code); // LINE A
System.out.println(s.getCode()); // LINE B
}
}
class Secret():
def __init__(self):
self._code = 42
def get_code(self):
return self._code
s = Secret()
print(s._code) # LINE A - actually runs in Python (prints 42), because the
# underscore is only a convention; Java refuses to compile
print(s.get_code()) # LINE B - the proper route in both languages
Line A: Compile error ဖြစ်ပါတယ်။ code က private ဖြစ်လို့ Main ကနေ သုံးလို့ မရပါဘူး။ (Python ကတော့ ဒီ line ကို run ပါလိမ့်မယ်၊ ဒါပေမယ့် _ နဲ့ စတဲ့ နာမည်က class ကိုယ်တိုင်နဲ့ပဲ သက်ဆိုင်တယ် ဆိုတဲ့ ရေးထုံးကို ချိုးဖောက်ပါတယ်။)
Line B: အလုပ်လုပ်ပါတယ်။ getCode() က public ဖြစ်ပြီး private field ရဲ့ တန်ဖိုးကို ပြန်ပေးပါတယ်။
ဒါက encapsulation ကို လက်တွေ့ အသုံးချထားတာပါ: ဒေတာကို ဖုံးထားပေမယ့် ထိန်းချုပ်ထားတဲ့ ဝင်ပေါက် (getter) ကို ပေးထားပါတယ်။
Quick Check (အမြန် စစ်ဆေးမေးခွန်း)
Q1. private access modifier က ဘာကို ဆိုလိုသလဲ။
Q2. ကောင်းကောင်း ဒီဇိုင်းဆွဲထားတဲ့ class တစ်ခုအတွက် စံ access modifier ပုံစံက ဘာလဲ။
Q3. Parent class ထဲက protected attribute တစ်ခုကို ဘယ်သူတွေ သုံးလို့ ရသလဲ။
Q4. တခြား class ကနေ private field ကို သုံးဖို့ ကြိုးစားရင် ဘာဖြစ်မလဲ။
Spot the Error (အမှား ရှာခြင်း)
ဒီ class က အလုပ်လုပ်ပေမယ့် design အားနည်းချက် တစ်ခု ရှိပါတယ်: member တစ်ခုမှာ access modifier မှားနေပါတယ်။ ပြဿနာရှိတဲ့ line ကို ရွေးပါ၊ ပြီးရင် ပြင်နည်းကို ရွေးပါ။
မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ:
Fill in the Blanks (ကွက်လပ် ဖြည့်ခြင်း)
Access modifier စည်းမျဉ်းတွေကို ဖြည့်ပါ။ အောက်က စာတွေက ဒီလို ဆိုလိုပါတယ်: Access Levels (most restrictive to least) က အတင်းကျပ်ဆုံးကနေ အလျော့ဆုံးအထိ access level များ၊ only within the same class က class တစ်ခုတည်းရဲ့ အထဲမှာသာ၊ same class + subclasses က class တစ်ခုတည်း နဲ့ subclass များ၊ any class can access က ဘယ် class မဆို သုံးလို့ရ၊ Standard Pattern က စံ ပုံစံ:
Access Levels (most restrictive to least)
==========================================
= only within the same class
= same class + subclasses
= any class can access
Standard Pattern
================
Attributes:
Getters/Setters:
Helper methods: Practice Exercises (လေ့ကျင့်ခန်းများ)
Core (အခြေခံ အဆင့်)
- Modifier စစ်ဆေးခြင်း: အောက်က member တစ်ခုစီက
private၊protectedဒါမှမဟုတ်publicဘယ်ဟာ ဖြစ်သင့်လဲ ဖော်ပြပြီး ဘာကြောင့်လဲ ရှင်းပြပါ:Recipe.servingsRecipe.getServings()Recipe.isValidServings(int)(setServings()ကပဲ သုံးပါတယ်)Vehicle.speed(Car နဲ့ Motorcycle subclass တွေ လိုအပ်ပါတယ်)
- Class ကို ပြင်ပါ: ဒီ class မှာ access modifier ပြဿနာ သုံးခု ရှိပါတယ်။ ရှာပြီး ပြင်ပါ:
public class Employee { private String name; public double salary; private String getName() { return name; } public boolean isValidSalary(double s) { return s >= 0; } }
Extension (တိုးချဲ့ အဆင့်)
- အစကနေ design လုပ်ခြင်း: ဆေးရုံ စနစ် တစ်ခုအတွက်
Patientclass တစ်ခုကို Design (အစီအစဉ် ဒါမှမဟုတ် model တစ်ခု ရေးဆွဲပါ) လုပ်ပါ။ ဘယ် member တွေကprivate၊publicဒါမှမဟုတ်protectedဖြစ်မလဲ ဆုံးဖြတ်ပါ။ ရွေးချယ်မှု တစ်ခုစီကို Justify (ဘာကြောင့် ရွေးတာလဲ အကြောင်းပြချက်နဲ့ ပြပါ) လုပ်ပါ။ Private ဖြစ်သင့်တဲ့ helper method အနည်းဆုံး တစ်ခု ထည့်ပါ။
Challenge (စိန်ခေါ်မှု အဆင့်)
- Access control (သုံးခွင့် ထိန်းချုပ်မှု) ကို ခွဲခြမ်းစိတ်ဖြာခြင်း:
Animal(parent)၊Dog(child) နဲ့Main(မဆိုင်တဲ့ class) ဆိုတဲ့ class တွေ ပေးထားပါတယ်။ Access level (private,protected,public) တစ်ခုစီအတွက် class တစ်ခုစီကAnimalရဲ့ ဘယ် member တွေကို သုံးလို့ရလဲ ပြတဲ့ ဇယား တစ်ခု ဆွဲပါ။ Level တစ်ခုစီကို ဘယ်အချိန်မှာ သုံးမလဲဆိုတဲ့ တိကျတဲ့ ဥပမာ တစ်ခုစီ ပေးပါ။
ဆက်စပ် ခေါင်းစဉ်များ
- အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Encapsulation: access modifier တွေက encapsulation ကို လက်တွေ့ ဖြစ်အောင် လုပ်ပေးတဲ့ tool ပါ
- နောက်ထပ် လေ့လာမယ့် ခေါင်းစဉ်: Static Members။
staticက access modifier မဟုတ်ပေမယ့် access modifier တွေနဲ့ မကြာခဏ ရောထွေးတတ်ပါတယ် - ရှေ့ဆက် ခေါင်းစဉ်: Inheritance။ Subclass တွေက parent ရဲ့ ဒေတာကို လိုအပ်တဲ့အခါ
protectedက အရေးကြီးလာပါတယ်