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) ဆိုတာ သတ်မှတ်ပါတယ်။ private member ကို သူ့ 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 နဲ့ public getter ကို တွဲသုံးတာ ပိုကောင်းပါတယ်၊ ဘာလို့လဲဆိုတော့ ဒေတာကို ဘယ်လို သုံးခွင့်ပေးမလဲဆိုတာကို 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 ကို ရွေးပါ၊ ပြီးရင် ပြင်နည်းကို ရွေးပါ။

1public class Password { 2 private String hash; 3 public Password(String plaintext) { hash = encrypt(plaintext); } 4 public boolean isValid(String text) { return text.length() >= 8; } 5 private String encrypt(String text) { return text.hashCode() + ""; } 6}

မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ:


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 (အခြေခံ အဆင့်)

  1. Modifier စစ်ဆေးခြင်း: အောက်က member တစ်ခုစီက private၊ protected ဒါမှမဟုတ် public ဘယ်ဟာ ဖြစ်သင့်လဲ ဖော်ပြပြီး ဘာကြောင့်လဲ ရှင်းပြပါ:
    • Recipe.servings
    • Recipe.getServings()
    • Recipe.isValidServings(int) (setServings() ကပဲ သုံးပါတယ်)
    • Vehicle.speed (Car နဲ့ Motorcycle subclass တွေ လိုအပ်ပါတယ်)
  2. 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 (တိုးချဲ့ အဆင့်)

  1. အစကနေ design လုပ်ခြင်း: ဆေးရုံ စနစ် တစ်ခုအတွက် Patient class တစ်ခုကို Design (အစီအစဉ် ဒါမှမဟုတ် model တစ်ခု ရေးဆွဲပါ) လုပ်ပါ။ ဘယ် member တွေက private၊ public ဒါမှမဟုတ် protected ဖြစ်မလဲ ဆုံးဖြတ်ပါ။ ရွေးချယ်မှု တစ်ခုစီကို Justify (ဘာကြောင့် ရွေးတာလဲ အကြောင်းပြချက်နဲ့ ပြပါ) လုပ်ပါ။ Private ဖြစ်သင့်တဲ့ helper method အနည်းဆုံး တစ်ခု ထည့်ပါ။

Challenge (စိန်ခေါ်မှု အဆင့်)

  1. 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 က အရေးကြီးလာပါတယ်

© EduCS.me. ကွန်ပျူတာသိပ္ပံ ပညာရေးအတွက် အရင်းအမြစ်တွေ စုထားတဲ့ နေရာပါ။ EduCS is an independent educational resource. It is not affiliated with, or endorsed by, the International Baccalaureate Organization. (EduCS ဟာ သီးခြား ပညာရေး အရင်းအမြစ်တစ်ခုပါ။ International Baccalaureate Organization နဲ့ ဆက်စပ်မှု မရှိသလို သူတို့ရဲ့ ထောက်ခံချက်လည်း မရှိပါဘူး။) ဆက်သွယ်ရန်