Object References (object ရှိရာ memory နေရာကို ညွှန်းတဲ့ တန်ဖိုးများ)
B3.1: Understand how objects are stored and referenced in memory.
မြန်မာလို: object (class တစ်ခုကနေ ဖန်တီးထားတဲ့ instance) တွေကို memory (မှတ်ဉာဏ်) ထဲမှာ ဘယ်လို သိမ်းပြီး ဘယ်လို ညွှန်းသလဲ ဆိုတာကို နားလည်ရပါမယ်။
အဓိက အယူအဆများ
Memory ထဲက primitive နဲ့ object
Java က primitive type (Java ရဲ့ အခြေခံ ဒေတာ အမျိုးအစား) တွေ (int, double, boolean, char) ကို variable (တန်ဖိုး သိမ်းထားတဲ့ နာမည်ပေးထားတဲ့ နေရာ) ထဲမှာ တိုက်ရိုက် သိမ်းပါတယ်: variable က တကယ့် တန်ဖိုးကို ကိုင်ထားပါတယ်။
Object တွေကိုတော့ Java က တခြားနည်းနဲ့ သိမ်းပါတယ်။ Variable က object ကိုယ်တိုင်ကို မကိုင်ထားပါဘူး: reference (memory ထဲမှာ object ရှိနေတဲ့ နေရာကို ညွှန်းပေးတဲ့ memory address၊ ဆိုလိုတာက နေရာ လိပ်စာ) ကို ကိုင်ထားပါတယ်။
Primitive: int age = 25;
age → [ 25 ] ← the value IS in the variable
Object: Student s = new Student("Alice");
s → [ address ] → [ name: "Alice", grade: 0 ]
↑ reference ↑ the actual object (in heap memory)
ပုံထဲက the value IS in the variable က တန်ဖိုးက variable ထဲမှာ တကယ် ရှိတယ်၊ reference က object ရဲ့ လိပ်စာ၊ the actual object (in heap memory) က heap memory (object တွေကို သိမ်းထားတဲ့ memory အပိုင်း) ထဲမှာ ရှိတဲ့ တကယ့် object လို့ ဆိုလိုပါတယ်။
ဒီ ကွာခြားချက်က assignment (variable ထဲ တန်ဖိုး ထည့်ခြင်း)၊ comparison (တန်ဖိုး နှစ်ခုကို နှိုင်းယှဉ်ခြင်း) နဲ့ method (သီးခြား အလုပ်တစ်ခု လုပ်ပေးတဲ့ code အပိုင်း) parameter တွေ အလုပ်လုပ်ပုံကို ပြောင်းစေလို့ အရေးကြီးပါတယ်။
Aliasing (variable နှစ်ခုက object တစ်ခုတည်းကို ညွှန်းခြင်း): Reference နှစ်ခု၊ Object တစ်ခု
Object variable တစ်ခုကို နောက်တစ်ခုထဲ assign လုပ်လိုက်ရင် object ကို copy ကူးတာ မဟုတ်ဘဲ reference ကို copy ကူးတာပါ။ အခု variable နှစ်ခုလုံးက memory ထဲက object တစ်ခုတည်းကို ညွှန်းနေပါပြီ။ ဒါကို aliasing လို့ ခေါ်ပါတယ်။
ဒီစာမျက်နှာက ဥပမာတွေမှာ ဒီ WaterTank (ရေတိုင်ကီ) class (object တွေ ဖန်တီးဖို့ ပုံစံခွက်) အသေးလေးကို သုံးပါတယ်: fill() က ရေ ထည့်ပေးပါတယ်၊ drain() က ရေ ထုတ်ပါတယ်၊ getLitres() က tank ထဲမှာ ရေ ဘယ်လောက် ရှိလဲ ပြန်ပေးပါတယ်။
public class WaterTank {
private String label;
private double litres;
public WaterTank(String label, double litres) {
this.label = label;
this.litres = litres;
}
public String getLabel() { return label; }
public double getLitres() { return litres; }
public void fill(double amount) {
if (amount > 0) {
litres = litres + amount;
}
}
public void drain(double amount) {
if (amount > 0 && amount <= litres) {
litres = litres - amount;
}
}
}
class WaterTank():
def __init__(self, label, litres):
self._label = label
self._litres = litres
def get_label(self):
return self._label
def get_litres(self):
return self._litres
def fill(self, amount):
if amount > 0:
self._litres = self._litres + amount
def drain(self, amount):
if amount > 0 and amount <= self._litres:
self._litres = self._litres - amount
WaterTank a1 = new WaterTank("Roof", 500.0);
WaterTank a2 = a1; // a2 copies the reference, NOT the object
a2.fill(200.0);
System.out.println(a1.getLitres()); // 700.0
System.out.println(a2.getLitres()); // 700.0
a1 = WaterTank("Roof", 500.0)
a2 = a1 # a2 copies the reference, NOT the object - exactly like Java
a2.fill(200.0)
print(a1.get_litres()) # 700.0
print(a2.get_litres()) # 700.0
a1 ရော a2 ပါ object တစ်ခုတည်းကို ညွှန်းနေပါတယ်။ a2 ကနေတစ်ဆင့် ရေ ထည့်လိုက်ရင် a1 ညွှန်းနေတဲ့ object လည်း ပြောင်းသွားပါတယ်။
Before: a1 ──┐
├──► [ Alice, 500.0 ] ← ONE object, two references
a2 ──┘
After: a1 ──┐
├──► [ Alice, 700.0 ] ← still ONE object, both see the change
a2 ──┘
ပုံထဲက Before က မတိုင်ခင်၊ After က ပြီးနောက်၊ ONE object, two references က object တစ်ခု၊ reference နှစ်ခု၊ still ONE object, both see the change က object တစ်ခုတည်းပါပဲ၊ နှစ်ခုလုံးက ပြောင်းလဲမှုကို မြင်ရတယ် လို့ ဆိုလိုပါတယ်။
ကျောင်းသားတွေက
a2 = a1ဆိုရင် သီးခြား copy တစ်ခု ဖန်တီးမယ်လို့ မကြာခဏ ထင်တတ်ကြပါတယ်။ ဒီလို မဟုတ်ပါဘူး: object တစ်ခုတည်းအတွက် ဒုတိယ နာမည် တစ်ခု ဖန်တီးတာပါ။ တကယ့် copy တစ်ခု လိုချင်ရင် object အသစ် တစ်ခု ဖန်တီးပြီး တန်ဖိုးတွေကို copy ကူးထည့်ရပါမယ်။
Primitive တွေနဲ့ နှိုင်းယှဉ်ကြည့်ခြင်း
Primitive တွေမှာ variable က တန်ဖိုးကို တိုက်ရိုက် ကိုင်ထားလို့ မတူတဲ့ပုံစံနဲ့ အလုပ်လုပ်ပါတယ်:
int x = 10;
int y = x; // copies the VALUE, not a reference
y = 20;
System.out.println(x); // 10 -- unchanged
System.out.println(y); // 20
# Python has no primitives - but numbers are IMMUTABLE (they cannot be
# changed in place), so the behaviour matches Java's value copy
x = 10
y = x
y = 20 # rebinds y to a new value; x is untouched
print(x) # 10 - unchanged
print(y) # 20
Variable တစ်ခုစီက တန်ဖိုးရဲ့ ကိုယ်ပိုင် သီးခြား copy ကို ကိုင်ထားလို့ y ကို ပြောင်းတာက x ကို မထိခိုက်ပါဘူး။
null: Object မရှိခြင်း
ဘယ် object ကိုမှ မညွှန်းတဲ့ reference variable က null (ဘာ object ကိုမှ မညွှန်းတဲ့ တန်ဖိုး) ဆိုတဲ့ အထူး တန်ဖိုးကို ကိုင်ထားပါတယ်။ “ဒီ variable ရှိပေမယ့် ဘာကိုမှ မညွှန်းဘူး” လို့ ဆိုလိုပါတယ်။
Student s = null; // s exists but points to no object
s = None # None is Python's null - s exists but points to no object
null reference ပေါ်မှာ method ကို ခေါ်ရင် NullPointerException (null reference ကို သုံးလို့ ဖြစ်တဲ့ အမှား) ဖြစ်ပါတယ်: Java မှာ အဖြစ်အများဆုံး runtime error (program run နေစဉ် ဖြစ်တဲ့ error) တွေထဲက တစ်ခုပါ:
Student s = null;
System.out.println(s.getName()); // NullPointerException!
s = None
print(s.get_name()) # AttributeError! (Python's version of the same crash)
ပြင်နည်း: method တွေကို မခေါ်ခင် null ဟုတ်မဟုတ် အမြဲ စစ်ပါ၊ အထူးသဖြင့် အကွက်တိုင်း ပြည့်ချင်မှ ပြည့်မယ့် object array (အရွယ်အစား ပုံသေ၊ အမျိုးအစားတူ ဒေတာစု) တွေနဲ့ အလုပ်လုပ်တဲ့အခါ:
if (s != null) {
System.out.println(s.getName());
}
if s != None:
print(s.get_name())
အလွတ် ဖြစ်နေနိုင်တဲ့ object array element (အစုထဲက အချက်) တွေပေါ်မှာ method မခေါ်ခင်
nullဟုတ်မဟုတ် စစ်ပါ။new Student[30]က Student object 30 ခု မဟုတ်ဘဲnullreference 30 ခုကို ဖန်တီးပါတယ်။
== နဲ့ .equals(): Object တွေကို နှိုင်းယှဉ်ခြင်း
Primitive တွေအတွက် == က တန်ဖိုးတွေကို နှိုင်းယှဉ်ပါတယ်:
int a = 5;
int b = 5;
System.out.println(a == b); // true -- same value
a = 5
b = 5
print(a == b) # True - same value
Object တွေအတွက်တော့ == က အထဲက ဒေတာကို မဟုတ်ဘဲ reference တွေ (memory address တွေ) ကို နှိုင်းယှဉ်ပါတယ်:
Student s1 = new Student("Alice", 11);
Student s2 = new Student("Alice", 11);
System.out.println(s1 == s2); // false -- different objects in memory
s1 = Student("Alice", 11)
s2 = Student("Alice", 11)
print(s1 == s2) # False - different objects in memory
# Python's == calls a special method (__eq__) which, unless a class defines
# its own, compares identity - so on our classes it behaves like Java's ==
s1 နဲ့ s2 မှာ ဒေတာ တူနေပေမယ့် သူတို့က memory address မတူတဲ့ သီးခြား object နှစ်ခုပါ။ == က object တွေထဲမှာ တန်ဖိုး တူမတူကို စစ်တာ မဟုတ်ဘဲ variable နှစ်ခုလုံး object တစ်ခုတည်း ကို ညွှန်းနေလား စစ်တာပါ။
Object တွေရဲ့ အကြောင်းအရာ (content) ကို နှိုင်းယှဉ်ချင်ရင် .equals() ကို သုံးပါ:
String a = new String("hello");
String b = new String("hello");
System.out.println(a == b); // false -- different objects
System.out.println(a.equals(b)); // true -- same content
a = "hello"
b = "hello"
print(a == b) # True - for strings, Python's == compares CONTENT,
# doing the job of Java's .equals()
# Python has no .equals() - == is the correct string comparison in Python
String (စာသား) တွေကို နှိုင်းယှဉ်ဖို့
.equals()ကို အမြဲ သုံးပါ၊==ကို ဘယ်တော့မှ မသုံးပါနဲ့။==operator (တန်ဖိုးတွေကို တွက်ချက်တဲ့ သင်္ကေတ) က String variable နှစ်ခုက memory ထဲက object တစ်ခုတည်းကို အတိအကျ ညွှန်းနေလား စစ်ပါတယ်၊ ဒါက များသောအားဖြင့် ကိုယ်လိုချင်တာ မဟုတ်ပါဘူး။"hello".equals(other)က character (စာလုံး ဒါမှမဟုတ် သင်္ကေတ) တွေ တူမတူ စစ်ပါတယ်။ (Python မှာတော့ ပြောင်းပြန်ပါ:==က string ရဲ့ အကြောင်းအရာကို နှိုင်းယှဉ်ပြီး ကိုယ်လိုချင်တာ အတိအကျ ဖြစ်ပါတယ်။)
.equals() က အကြောင်းအရာကို နှိုင်းယှဉ်တာက String class က အဲဒီလို သတ်မှတ်ထားလို့သာ ဖြစ်ပါတယ်။ Student လို ကိုယ်တိုင် ရေးတဲ့ class တစ်ခုမှာတော့ Object ကနေ အမွေဆက်ခံထားတဲ့ ပုံစံနဲ့ စပါတယ်။ အဲဒီ ပုံစံက == လိုပဲ reference တွေကို နှိုင်းယှဉ်ပါတယ်: နာမည်နဲ့ grade တူတဲ့ Student နှစ်ယောက်အတွက် s1.equals(s2) က false ပါ။ .equals() ကို field (object ထဲက အချက်အလက် အကွက်) တွေ နှိုင်းယှဉ်အောင် လုပ်ချင်ရင် class က သူ့ကို override (parent ရဲ့ method ကို child က အစားထိုး ရေးခြင်း) လုပ်ရပါမယ် (ဒီစာမျက်နှာ အပြင်က အကြောင်းအရာပါ)။ အခုအတွက်တော့ String တွေနဲ့ .equals() ကို သတ်မှတ်ထားတဲ့ class တွေမှာ အလုပ်လုပ်တယ်လို့ မှတ်ထားပါ။
Object တွေကို method တွေဆီ ပေးပို့ခြင်း
Primitive တစ်ခုကို method ဆီ ပေးပို့ရင် Java က တန်ဖိုးကို copy ကူးပါတယ်။ Method က သူ့ကိုယ်ပိုင် copy နဲ့ အလုပ်လုပ်ပါတယ်: ပြောင်းလဲမှုတွေက မူလ တန်ဖိုးကို မထိခိုက်ပါဘူး။
Object တစ်ခုကို method ဆီ ပေးပို့ရင်တော့ Java က reference ကို copy ကူးပါတယ်။ Method က object တစ်ခုတည်း ကို ညွှန်းတဲ့ reference ကို လက်ခံရပါတယ်: method ထဲမှာ object ကို ပြောင်းလိုက်တာတွေကို caller (ခေါ်တဲ့ method) က မြင်ရပါတယ်။
public static void doubleWater(WaterTank tank) {
double current = tank.getLitres();
tank.fill(current); // modifies the ORIGINAL object
}
WaterTank myTank = new WaterTank("Roof", 100.0);
doubleWater(myTank);
System.out.println(myTank.getLitres()); // 200.0 -- changed!
def double_water(tank): # a free-standing function receiving the object
current = tank.get_litres()
tank.fill(current) # modifies the ORIGINAL object
my_tank = WaterTank("Roof", 100.0)
double_water(my_tank)
print(my_tank.get_litres()) # 200.0 - changed!
# Python passes references the same way: changing the object inside
# the function is visible to the caller
Method က reference ရဲ့ copy (object တစ်ခုတည်းကို ညွှန်းတဲ့ copy) ကို လက်ခံရလို့ tank.fill() က myTank ညွှန်းနေတဲ့ object တစ်ခုတည်းကိုပဲ ပြောင်းပါတယ်။
အဆင့်ဆင့် ရှင်းပြထားတဲ့ ဥပမာများ
ဥပမာ 1: Alias ဖြစ်နေတဲ့ reference တွေကို တစ်ဆင့်ချင်း လိုက်ကြည့်ခြင်း
WaterTank a = new WaterTank("Roof", 1000.0);
WaterTank b = new WaterTank("Garden", 500.0);
WaterTank c = a; // c is an alias for a
c.fill(300.0);
b.fill(100.0);
a = WaterTank("Roof", 1000.0)
b = WaterTank("Garden", 500.0)
c = a # c is an alias for a
c.fill(300.0)
b.fill(100.0)
| ဘယ် line ပြီးနောက် | a.litres | b.litres | c.litres | မှတ်ချက် |
|---|---|---|---|---|
| Line 1-2 | 1000.0 | 500.0 | - | သီးခြား object နှစ်ခု |
| Line 3 | 1000.0 | 500.0 | 1000.0 | c က a နဲ့ object တစ်ခုတည်း ကို ညွှန်းပါတယ် |
| Line 4 | 1300.0 | 500.0 | 1300.0 | c.fill က a ရဲ့ object ကိုပါ ပြောင်းပါတယ် |
| Line 5 | 1300.0 | 600.0 | 1300.0 | b က သီးခြား ဖြစ်ပါတယ် |
ဥပမာ 2: Null ဟုတ်မဟုတ် စစ်တဲ့ ပုံစံ
Student[] roster = new Student[5];
roster[0] = new Student("Alice", 95);
roster[1] = new Student("Bob", 82);
// roster[2], [3], [4] are still null
int count = 0;
for (int i = 0; i < roster.length; i++) {
if (roster[i] != null && roster[i].getGrade() > 90) {
count++;
}
}
System.out.println(count); // 1 (only Alice)
# Python lists normally start empty, but a list of Nones mirrors
# Java's array of null references for this example
roster = [None] * 5 # five None ("null") entries
roster[0] = Student("Alice", 95)
roster[1] = Student("Bob", 82)
# roster[2], [3], [4] are still None
count = 0
for i in range(len(roster)):
if roster[i] != None and roster[i].get_grade() > 90:
count = count + 1
print(count) # 1 (only Alice)
roster[i] != null စစ်ဆေးချက်က အရင်ဆုံး လာရပါမယ်။ Java က short-circuit evaluation (ဘယ်ဘက်ကို ကြည့်ရုံနဲ့ အဖြေ သိရင် ညာဘက်ကို ဆက်မတွက်ခြင်း) ကို သုံးပါတယ်: && ရဲ့ ဘယ်ဘက်က false ဆိုရင် ညာဘက်ကို ဘယ်တော့မှ မတွက်ပါဘူး။ Null စစ်ဆေးချက် မပါရင် roster[2].getGrade() က NullPointerException ကို throw (exception ဖြစ်ကြောင်း အချက်ပြ) လုပ်ပါလိမ့်မယ်။ (Python ရဲ့ and ကလည်း အဲဒီလိုပဲ short-circuit လုပ်လို့ AttributeError ကို ကာကွယ်ပေးပါတယ်။)
Quick Check (အမြန် စစ်ဆေးမေးခွန်း)
Q1. WaterTank b = a; က ဘာလုပ်သလဲ။
Q2. s က null ဖြစ်နေချိန်မှာ s.getName() ကို ခေါ်ရင် ဘာဖြစ်မလဲ။
Q3. Student object နှစ်ခုမှာ name နဲ့ grade တူနေပါတယ်။ s1 == s2 က ဘာကို ပြန်ပေးမလဲ။
Q4. WaterTank object တစ်ခုကို method ဆီ ပေးပို့ပြီး method က fill() ကို ခေါ်ရင် မူလ object ပြောင်းသွားသလား။
Trace Exercise (code ကို တစ်ဆင့်ချင်း လိုက်ကြည့်ခြင်း)
ဒီ code တစ်လျှောက် reference တွေနဲ့ object state (object ထဲမှာ လက်ရှိ ရှိနေတဲ့ တန်ဖိုးများ) ကို trace (တစ်ဆင့်ချင်း လိုက်ပြီး မှတ်) လုပ်ပါ။ နောက်ဆုံး ကော်လံ (z ညွှန်းနေတဲ့ object) မှာ variable နာမည်ကို English စာလုံးနဲ့ ရိုက်ထည့်ပါ (ဥပမာ x ဒါမှမဟုတ် y)။
Trace: Aliasing နဲ့ သီးခြား ဖြစ်ခြင်း
WaterTank x = new WaterTank("Roof", 100.0);
WaterTank y = new WaterTank("Garden", 200.0);
WaterTank z = x;
z.fill(50.0);
y.fill(25.0);| ဘယ် line ပြီးနောက် | x.litres | y.litres | z ညွှန်းနေတဲ့ object |
|---|---|---|---|
| Line 1-2 | 100.0 | 200.0 | -- |
| Line 3: z = x | |||
| Line 4: z.fill(50) | |||
| Line 5: y.fill(25) |
Spot the Error (အမှား ရှာခြင်း)
String နှစ်ခုလုံးမှာ "hello" ပါပေမယ့် ဒီ code က "different" လို့ print ထုတ်ပါတယ်။ အမှားပါတဲ့ line ကို ရွေးပါ၊ ပြီးရင် ပြင်နည်းကို ရွေးပါ။
မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ:
Predict the Output (output ကို ကြိုခန့်မှန်းခြင်း)
ဒီ code က ဘာကို print ထုတ်မလဲ။
WaterTank a = new WaterTank("Roof", 500.0);
WaterTank b = a;
b.fill(100.0);
System.out.println(a.getLitres()); ဒီ code က ဘာကို print ထုတ်မလဲ။
int x = 10;
int y = x;
y = 99;
System.out.println(x); Practice Exercises (လေ့ကျင့်ခန်းများ)
Core (အခြေခံ အဆင့်)
- Output ကို ကြိုခန့်မှန်းပါ: ဒီ code ကို trace လုပ်ပြီး
printlnတစ်ခုစီက ဘာ output ထုတ်မလဲ ကြိုခန့်မှန်းပါ။ ဘာကြောင့်လဲ ရှင်းပြပါ။Student s1 = new Student("Alice", 90); Student s2 = s1; Student s3 = new Student("Alice", 90); System.out.println(s1 == s2); System.out.println(s1 == s3); -
Null စစ်ဆေးခြင်း လေ့ကျင့်ခန်း: Grade 50 နဲ့ အထက် ရတဲ့ ကျောင်းသား အရေအတွက်ကို ပြန်ပေးတဲ့
countPassing(Student[] students)method ကို ရေးပါ။ Array ထဲမှာnullအကွက်တွေ ပါနိုင်ပါတယ်။ Null စစ်ဆေးချက်ကို ထည့်ပါ။ - ကွာခြားချက်ကို ရှင်းပြပါ:
int a = 5; int b = 5;အတွက်==ကtrueပြန်ပေးပြီး ဒေတာ တူတဲ့ Student object နှစ်ခုအတွက်တော့falseပြန်ပေးတာ ဘာကြောင့်လဲ ဆိုတာကို ကိုယ့်စကားနဲ့ ရှင်းပြပါ။
Extension (တိုးချဲ့ အဆင့်)
- Reference တွေကို trace လုပ်ခြင်း: အဆင့်တိုင်းမှာ ဘာဖြစ်လဲ ပြတဲ့ memory diagram (memory ထဲက အခြေအနေကို ပြတဲ့ ပုံ) တစ်ခု ဆွဲပါ:
Student a = new Student("Alice", 90); Student b = new Student("Bob", 80); Student c = a; a = b; b = c;Line ငါးကြောင်းလုံး ပြီးတဲ့အခါ
a၊bနဲ့cက ဘာကို ညွှန်းနေလဲ။ ဒေတာ တစ်ခုခု ပျောက်သွားသလား။ - Method parameter တွေ အလုပ်လုပ်ပုံ: ဒီ method က မူလ tank ရဲ့ litres ကို ပြောင်းပေမယ့်
myTankညွှန်းနေတဲ့ object ကိုတော့ မပြောင်း တာ ဘာကြောင့်လဲ ရှင်းပြပါ:public static void reset(WaterTank tank) { tank.drain(tank.getLitres()); // empties the tank tank = new WaterTank("New", 0); // does NOT affect the caller }
Challenge (စိန်ခေါ်မှု အဆင့်)
- Deep copy (လုံးဝ သီးခြား ဖြစ်တဲ့ copy):
Studentclass မှာname(String) နဲ့grade(int) ရှိပါတယ်။ လုံးဝ သီးခြား ဖြစ်တဲ့ copy တစ်ခု (တန်ဖိုး တူတဲ့ object အသစ် တစ်ခု) ကို ဖန်တီးပြီး return ပြန်ပေးတဲ့copyStudent(Student original)method ကို ရေးပါ။ Copy ကို ပြောင်းကြည့်ပြီး မူလ object မပြောင်းကြောင်း ပြခြင်းအားဖြင့် ကိုယ့် copy က သီးခြား ဖြစ်ကြောင်း သက်သေပြပါ။
ဆက်စပ် ခေါင်းစဉ်များ
- အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Classes and Objects:
newနဲ့ object တွေ ဖန်တီးခြင်း - အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: The
thisKeyword:thisက လက်ရှိ object ကို ညွှန်းတဲ့ reference ပါ - ဆက်စပ် ခေါင်းစဉ်: Strings: String တွေကို
.equals()နဲ့==သုံးပြီး နှိုင်းယှဉ်ခြင်း - နောက်ထပ် လေ့လာမယ့် ခေါင်းစဉ်: UML Class Diagrams (class တစ်ခုကို အကွက် သုံးကွက်နဲ့ ပြတဲ့ ပုံ)။ Class တွေရဲ့ ဖွဲ့စည်းပုံနဲ့ ဆက်နွယ်မှုတွေကို ပုံနဲ့ ပြခြင်း
- ရှေ့ဆက် ခေါင်းစဉ်: Aggregation (သီးခြား ရှိနေနိုင်တဲ့ has-a ဆက်နွယ်မှု)။ Object တွေကို attribute (object ရဲ့ ဒေတာကို သိမ်းတဲ့ variable) အဖြစ် ထားရင် reference ကွင်းဆက်တွေ ဖြစ်လာပါတယ်