Composition vs Inheritance (composition နဲ့ inheritance နှိုင်းယှဉ်ချက်)
B3.2.4 (HL): Explain the role of composition and aggregation in class relationships.
မြန်မာလို: class (object တွေ ဖန်တီးဖို့ ပုံစံခွက်) တွေကြားက ဆက်နွယ်မှုတွေမှာ composition (ပိုခိုင်မာတဲ့ has-a ဆက်နွယ်မှု) နဲ့ aggregation (သီးခြား ရှိနေနိုင်တဲ့ has-a ဆက်နွယ်မှု) ရဲ့ အခန်းကဏ္ဍကို ရှင်းပြနိုင်ရပါမယ်။
ဒီစာမျက်နှာက HL အဆင့်မှာပဲ စစ်ဆေးတဲ့ အကြောင်းအရာ ဖြစ်ပါတယ်။ SL (Standard Level) နဲ့ HL (Higher Level) ဆိုတာ IB Computer Science (နိုင်ငံတကာ ကျောင်းတွေမှာ သင်တဲ့ ကွန်ပျူတာသိပ္ပံ သင်ရိုး) သင်တန်းရဲ့ အဆင့်နှစ်ဆင့် ဖြစ်ပြီး HL အပိုင်းတွေက ပိုနက်နက်ရှိုင်းရှိုင်း လေ့လာရတဲ့ အပိုင်းတွေပါ။
အဓိက အယူအဆများ
ရှုပ်ထွေးတဲ့ Object တွေကို တည်ဆောက်တဲ့ နည်းလမ်း နှစ်မျိုး
Class အများ ပါတဲ့ program တစ်ခုကို design လုပ်တဲ့အခါ class တွေကို အချင်းချင်း ဆက်စပ်ပေးဖို့ အခြေခံ နည်းလမ်း နှစ်မျိုး ရှိပါတယ်:
- Inheritance (is-a):
DogIS-AAnimal၊ ဆိုလိုတာကDogကAnimalတစ်မျိုး ဖြစ်ပါတယ်။ Child class က parent class ကို extend (အမွေဆက်ခံ) လုပ်ပြီး parent ရဲ့ attribute (object ရဲ့ ဒေတာကို သိမ်းတဲ့ variable) တွေနဲ့ method (သီးခြား အလုပ်တစ်ခု လုပ်ပေးတဲ့ code အပိုင်း) တွေကို အမွေဆက်ခံပါတယ်။ - Composition (has-a):
CarHAS-AEngine၊ ဆိုလိုတာကCarထဲမှာEngine(အင်ဂျင်) ပါပါတယ်။ Object (class တစ်ခုကနေ ဖန်တီးထားတဲ့ instance) တစ်ခုက နောက် object တစ်ခုကို attribute အဖြစ် ထည့်ထားပါတယ်။
နည်းလမ်း နှစ်မျိုးလုံးက code ကို ပြန်သုံးခွင့် ပေးပေမယ့် အလုပ်လုပ်ပုံ မတူသလို သင့်တော်တဲ့ အခြေအနေတွေလည်း မတူပါဘူး။
Composition (ပိုခိုင်မာတဲ့ has-a ဆက်နွယ်မှု)
Composition ဆိုတာ class တစ်ခုက သူ့ကို ဖွဲ့စည်းထားတဲ့ object တွေကို ကိုယ်တိုင် ဖန်တီးပြီး attribute တွေအဖြစ် သိမ်းထားတာပါ။ အဲဒီ အစိတ်အပိုင်းတွေက အဲဒီ object တစ်ခုတည်းရဲ့ ပိုင်ဆိုင်မှုပါ: သူ့အထဲမှာ ဖန်တီးတယ်၊ တခြား ဘယ် object ကမှ မကိုင်ထားဘူး၊ သူ မရှိတော့ရင် သူတို့လည်း မရှိတော့ဘူး။
public class Engine {
private int horsepower;
public Engine(int horsepower) {
this.horsepower = horsepower;
}
public void start() {
System.out.println("Engine starting (" + horsepower + " HP)");
}
public int getHorsepower() { return horsepower; }
}
public class Car {
private String model;
private Engine engine; // Car HAS-A Engine
public Car(String model, int hp) {
this.model = model;
this.engine = new Engine(hp); // Engine created WITH the Car
}
public void drive() {
engine.start();
System.out.println(model + " is driving");
}
}
class Engine():
def __init__(self, horsepower):
self._horsepower = horsepower
def start(self):
print("Engine starting (" + str(self._horsepower) + " HP)")
def get_horsepower(self):
return self._horsepower
class Car():
def __init__(self, model, hp):
self._model = model
self._engine = Engine(hp) # Car HAS-A Engine, created WITH the Car
def drive(self):
self._engine.start()
print(self._model, "is driving")
Car car = new Car("Tesla Model 3", 283);
car.drive();
car = Car("Tesla Model 3", 283)
car.drive()
Output (program က ထုတ်ပြတဲ့ ရလဒ်):
Engine starting (283 HP)
Tesla Model 3 is driving
Engine ကို Car constructor (object ဖန်တီးချိန် attribute တွေကို စတင် သတ်မှတ်ပေးတဲ့ method) ထဲမှာ ဖန်တီးပြီး Car က သူ့ဆီကို ညွှန်းတဲ့ တစ်ခုတည်းသော reference (object ရှိရာ memory နေရာကို ညွှန်းတဲ့ တန်ဖိုး) ကို ကိုင်ထားပါတယ်။ Program ရဲ့ တခြား ဘယ်အပိုင်းကမှ အဲဒီ engine ကို မရောက်နိုင်တာမို့ car မရှိတော့တာနဲ့ engine လည်း မရှိတော့ပါဘူး။ ဒါက lifecycle dependency (အစိတ်အပိုင်းရဲ့ သက်တမ်းက တစ်ခုလုံးပေါ် မူတည်ခြင်း) ပါ: အစိတ်အပိုင်းက တစ်ခုလုံး ရှိနေသရွေ့ပဲ ရှိပါတယ်။
Composition = lifecycle dependency။ Container (အစိတ်အပိုင်းတွေကို ကိုင်ထားတဲ့ object) က အစိတ်အပိုင်းကို ဖန်တီးပြီး သူ့ဆီကို ညွှန်းတဲ့ တစ်ခုတည်းသော reference ကို ကိုင်ထားတာမို့ အစိတ်အပိုင်းက container နဲ့အတူ ရှိလာပြီး container နဲ့အတူ ပျောက်သွားပါတယ်။ ဒီ code မှာ car နဲ့ သီးခြား ရှိနေတဲ့ engine ဆိုတာ မရှိပါဘူး။
Aggregation (သီးခြား ရှိနေနိုင်တဲ့ has-a ဆက်နွယ်မှု)
Aggregation က has-a ရဲ့ ပိုလျော့ရဲတဲ့ ပုံစံပါ။ Container ကို ရှိပြီးသား object တစ်ခု ပေးလိုက်ပြီး container က အဲဒီ object ရဲ့ reference ကို သိမ်းထားပါတယ်၊ ဒါကြောင့် အဲဒီ object ကို တခြား container တွေနဲ့ မျှသုံးလို့ ရပြီး container မရှိတော့ပြီးနောက်မှာလည်း ဆက်ရှိနေနိုင်ပါတယ်။
Class အတွဲ တစ်တွဲတည်းက နှစ်မျိုးထဲက ဘယ်ဟာမဆို ဖြစ်နိုင်ပါတယ်။ Aggregation စာမျက်နှာမှာ Car ကို တခြားနေရာမှာ ဖန်တီးထားတဲ့ Engine တစ်ခု ပေးပါတယ် (new Car(engine))၊ ဒါကြောင့် engine က သူ့ဘာသာ ရှိနေပြီး တခြား car ဆီ ရွှေ့လို့ ရပါတယ်: ဒါက aggregation ပါ။ ဒီမှာတော့ Car က သူ့ Engine ကို ကိုယ်တိုင် ဖန်တီးတာမို့ composition ဖြစ်ပါတယ်။ Code က ဆုံးဖြတ်ပါတယ်: အစိတ်အပိုင်းကို ဘယ်သူ ဖန်တီးလဲ၊ အစိတ်အပိုင်းက တစ်ခုလုံး မရှိတော့ပြီးနောက်မှာ ဆက်ရှိနေနိုင်လား ဆိုတာပါ။
public class Student {
private String name;
public Student(String name) {
this.name = name;
}
public String getName() { return name; }
}
public class Course {
private String title;
private Student[] students;
private int count;
public Course(String title, int maxSize) {
this.title = title;
this.students = new Student[maxSize];
this.count = 0;
}
public void enrol(Student s) {
if (count < students.length) {
students[count] = s;
count++;
}
}
public void printRoster() {
System.out.println(title + " roster:");
for (int i = 0; i < count; i++) {
System.out.println(" " + students[i].getName());
}
}
}
class Student():
def __init__(self, name):
self._name = name
def get_name(self):
return self._name
class Course():
def __init__(self, title, max_size):
self._title = title
self._students = [] # a Python list grows as needed - no separate count variable
self._max_size = max_size
def enrol(self, s):
if len(self._students) < self._max_size:
self._students.append(s)
def print_roster(self):
print(self._title + " roster:")
for i in range(len(self._students)):
print(" " + self._students[i].get_name())
Student alice = new Student("Alice");
Student bob = new Student("Bob");
Course cs = new Course("Computer Science", 30);
cs.enrol(alice);
cs.enrol(bob);
Course maths = new Course("Mathematics", 30);
maths.enrol(alice); // Alice is in BOTH courses
cs.printRoster();
alice = Student("Alice")
bob = Student("Bob")
cs = Course("Computer Science", 30)
cs.enrol(alice)
cs.enrol(bob)
maths = Course("Mathematics", 30)
maths.enrol(alice) # Alice is in BOTH courses
cs.print_roster()
Output:
Computer Science roster:
Alice
Bob
Student object တွေကို Course ရဲ့ အပြင်မှာ ဖန်တီးပြီး ပေးပို့ပါတယ်။ Course ကို ဖျက်လိုက်ရင်တောင် Student တွေက ဆက်ရှိနေပါတယ်။ Alice က course နှစ်ခုမှာ တစ်ပြိုင်နက် စာရင်းသွင်းထားပါတယ်: သူက ဘယ် course တစ်ခုကိုမှ သီးသန့် “ပိုင်” တာ မဟုတ်ပါဘူး။
Aggregation = သီးခြား ရှိနေနိုင်ခြင်း။ ပါဝင်နေတဲ့ object ကို တခြားနေရာမှာ ဖန်တီးပြီး မျှသုံးပါတယ်။ Playlist ကို ဖျက်လိုက်တာက သီချင်းတွေကို မဖျက်ပါဘူး။ ကျောင်းသားကို course ထဲကနေ ဖယ်လိုက်တာက ကျောင်းသားကို မဖျက်ပါဘူး။
Composition နဲ့ Aggregation အနှစ်ချုပ်
| Composition | Aggregation | |
|---|---|---|
| ဆက်နွယ်မှု | ခိုင်မာတဲ့ has-a | လျော့ရဲတဲ့ has-a |
| သက်တမ်း (lifecycle) | အစိတ်အပိုင်းက တစ်ခုလုံးနဲ့အတူ ပျက်သွားတယ် | အစိတ်အပိုင်းက သီးခြား ဆက်ရှိနေတယ် |
| ဖန်တီးပုံ | Container က အစိတ်အပိုင်းကို ဖန်တီးတယ် | အစိတ်အပိုင်းကို အပြင်မှာ ဖန်တီးပြီး ပေးပို့တယ် |
| မျှသုံးခြင်း | အစိတ်အပိုင်းက container တစ်ခုတည်းရဲ့ ပိုင်ဆိုင်မှုပါ | အစိတ်အပိုင်းကို container အများ မျှသုံးလို့ ရတယ် |
| ဥပမာ | ကိုယ်ပိုင် Engine ကို ဖန်တီးတဲ့ Car | Course has-a Student |
| UML (class တွေကို ပုံနဲ့ ပြတဲ့ စံ ရေးဆွဲနည်း) | အပြည့်ခြယ်ထားတဲ့ စိန်ပုံ (filled diamond) | အလွတ် စိန်ပုံ (empty diamond) |
Inheritance နဲ့ Composition ကို ဘယ်အချိန် သုံးမလဲ
Inheritance ကို ဒီလို အခြေအနေမှာ သုံးပါ:
- တကယ့် is-a ဆက်နွယ်မှု ရှိတဲ့အခါ (
DogIS-AAnimal) - Child က parent ရဲ့ behaviour (object က လုပ်နိုင်တာတွေ) ကို တကယ် specialise (ပိုသီးသန့်အောင် ပြင်) လုပ်တဲ့အခါ
- Polymorphism (ပုံစံ အမျိုးမျိုး ယူနိုင်ခြင်း) ကို လိုချင်တဲ့အခါ (child object တွေကို ကိုင်ထားတဲ့ parent-type array (အရွယ်အစား ပုံသေ၊ အမျိုးအစားတူ ဒေတာစု) တွေ)
ဒီအပိုင်းနဲ့ နောက်အပိုင်းမှာ composition ဆိုတာ ဘယ် has-a ဆက်နွယ်မှုကိုမဆို ဆိုလိုတာမို့ aggregation ကိုလည်း ပါဝင်ပါတယ်။ အောက်က design လမ်းညွှန်ချက်က ဒီစကားလုံးကို ဒီ အဓိပ္ပာယ်နဲ့ သုံးပါတယ်။
Composition ကို ဒီလို အခြေအနေမှာ သုံးပါ:
- Has-a ဆက်နွယ်မှု ရှိတဲ့အခါ (
CarHAS-AEngine) - မတူတဲ့ နေရာ အများကနေ စွမ်းရည်တွေကို ပေါင်းစပ်ချင်တဲ့အခါ
- ဆက်နွယ်မှုက runtime (program run နေစဉ်) မှာ ပြောင်းနိုင်တဲ့အခါ (engine တစ်ခုကို နောက်တစ်ခုနဲ့ လဲတာမျိုး)
- ပါဝင်နေတဲ့ object က သူ့ဘာသာ အဓိပ္ပာယ် ရှိတဲ့အခါ
အဖြစ်များတဲ့ အမှား: composition က ပိုသင့်တော်တဲ့ နေရာမှာ inheritance ကို သုံးမိတာပါ။ Method တချို့ကို ပြန်သုံးဖို့သက်သက် child class တစ်ခု ဖန်တီးနေမိပြီး is-a ဆက်နွယ်မှုက အတင်းအကျပ် ဖြစ်နေသလို ခံစားရရင် များသောအားဖြင့် composition က ပိုကောင်းတဲ့ ရွေးချယ်မှုပါ။ “
StackIS-AArrayList” ဆိုတာ မှားပါတယ်: Stack (အပေါ်ကနေပဲ ထည့်၊ ထုတ်တဲ့ အထပ်) က ArrayList (ကြီးလာ၊ သေးသွားနိုင်တဲ့ list) တစ်မျိုး မဟုတ်ပါဘူး၊ အထဲမှာ list တစ်ခုကို ကိုင်ထားတာပါ (HAS-A)။
“Favour Composition” Principle (composition ကို ဦးစားပေးရမယ်ဆိုတဲ့ မူ)
လူအများ သုံးတဲ့ design လမ်းညွှန်ချက် တစ်ခုက favour composition over inheritance (inheritance ထက် composition ကို ဦးစားပေးပါ) လို့ ဆိုပါတယ်။ ဒါက “inheritance ကို ဘယ်တော့မှ မသုံးနဲ့” လို့ ဆိုလိုတာ မဟုတ်ပါဘူး။ ဆိုလိုတာက:
- Inheritance က tight coupling (class တွေ အချင်းချင်း အလွန် မှီခိုနေခြင်း) ကို ဖြစ်စေပါတယ်: parent ကို ပြောင်းရင် child အားလုံး ပျက်သွားနိုင်ပါတယ်
- Composition က loose coupling (class တွေ အချင်းချင်း သိပ် မမှီခိုခြင်း) ကို ဖြစ်စေပါတယ်: container က အလုပ်ကို ပါဝင်နေတဲ့ object ဆီ delegate (အလုပ်ကို တခြား object ဆီ လွှဲပေး) လုပ်ပြီး အဲဒီ object ကို အစားထိုးလို့ ရပါတယ်
- Inheritance က compile time (compile လုပ်ချိန်) မှာ ပုံသေ ဖြစ်သွားပါတယ်: Dog ကို Cat အဖြစ် ပြောင်းလို့ မရပါဘူး
- Composition က runtime မှာ ပြောင်းလွယ်ပြင်လွယ် ရှိပါတယ်: Engine ကို တခြား engine တစ်ခုနဲ့ လဲလို့ ရပါတယ်
တကယ့် type hierarchy (parent နဲ့ child class တွေကို အဆင့်ဆင့် ဖွဲ့ထားတဲ့ ပုံစံ) တွေအတွက် inheritance ကို သုံးပါ။ ကျန်တာ အားလုံးအတွက် composition ကို သုံးပါ။
အဆင့်ဆင့် ရှင်းပြထားတဲ့ ဥပမာများ
ဥပမာ 1: စာကြည့်တိုက် စနစ်
စာကြည့်တိုက် တစ်ခုမှာ စာအုပ်တွေ ရှိပြီး စာအုပ် တစ်အုပ်စီမှာ စာရေးဆရာ (author) တစ်ယောက် ရှိပါတယ်။ Book က Author ကို extend လုပ်သင့်သလား။ မလုပ်သင့်ပါဘူး: စာအုပ်က စာရေးဆရာ မဟုတ်ပါဘူး (IS-NOT)။ စာအုပ်မှာ စာရေးဆရာ ရှိပါတယ် (HAS-A)။
public class Author {
private String name;
private String nationality;
public Author(String name, String nationality) {
this.name = name;
this.nationality = nationality;
}
public String getName() { return name; }
public String getNationality() { return nationality; }
}
public class Book {
private String title;
private Author author; // aggregation: Book HAS-A Author, passed in from outside
private int pages;
public Book(String title, Author author, int pages) {
this.title = title;
this.author = author;
this.pages = pages;
}
public String describe() {
return title + " by " + author.getName() +
" (" + author.getNationality() + "), " + pages + " pages";
}
}
class Author():
def __init__(self, name, nationality):
self._name = name
self._nationality = nationality
def get_name(self):
return self._name
def get_nationality(self):
return self._nationality
class Book():
def __init__(self, title, author, pages):
self._title = title
self._author = author # aggregation: Book HAS-A Author, passed in from outside
self._pages = pages
def describe(self):
return self._title + " by " + self._author.get_name() + \
" (" + self._author.get_nationality() + "), " + str(self._pages) + " pages"
Author orwell = new Author("George Orwell", "British");
Book b1 = new Book("1984", orwell, 328);
Book b2 = new Book("Animal Farm", orwell, 112);
System.out.println(b1.describe());
System.out.println(b2.describe());
orwell = Author("George Orwell", "British")
b1 = Book("1984", orwell, 328)
b2 = Book("Animal Farm", orwell, 112)
print(b1.describe())
print(b2.describe())
Output:
1984 by George Orwell (British), 328 pages
Animal Farm by George Orwell (British), 112 pages
ဒါက aggregation ပါ: Author object တစ်ခုတည်းကို စာအုပ် နှစ်အုပ်က မျှသုံးပါတယ်။ စာအုပ်ကို ဖျက်လိုက်တာက author ကို မဖျက်ပါဘူး။
ဥပမာ 2: Inheritance နဲ့ Composition ကို ပေါင်းသုံးခြင်း
ကျောင်း စီမံခန့်ခွဲရေး စနစ် တစ်ခုမှာ Teacher နဲ့ Student class တွေ (နှစ်ခုလုံး Person ဖြစ်ပါတယ်) နဲ့ ဆရာတွေ ပါဝင်တဲ့ Department တစ်ခု လိုပါတယ်။
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
public class Teacher extends Person {
private String subject;
public Teacher(String name, int age, String subject) {
super(name, age);
this.subject = subject;
}
public String getSubject() { return subject; }
}
public class Department {
private String name;
private Teacher[] staff;
private int count;
public Department(String name, int maxStaff) {
this.name = name;
this.staff = new Teacher[maxStaff];
this.count = 0;
}
public void addTeacher(Teacher t) {
if (count < staff.length) {
staff[count] = t;
count++;
}
}
public void printStaff() {
System.out.println(name + " department:");
for (int i = 0; i < count; i++) {
System.out.println(" " + staff[i].getName() +
" (" + staff[i].getSubject() + ")");
}
}
}
class Person():
def __init__(self, name, age):
self._name = name
self._age = age
def get_name(self):
return self._name
def get_age(self):
return self._age
class Teacher(Person):
def __init__(self, name, age, subject):
super().__init__(name, age) # call the parent constructor
self._subject = subject
def get_subject(self):
return self._subject
class Department():
def __init__(self, name, max_staff):
self._name = name
self._staff = [] # list grows as teachers are added
self._max_staff = max_staff
def add_teacher(self, t):
if len(self._staff) < self._max_staff:
self._staff.append(t)
def print_staff(self):
print(self._name + " department:")
for i in range(len(self._staff)):
print(" " + self._staff[i].get_name() +
" (" + self._staff[i].get_subject() + ")")
Teacher t1 = new Teacher("Ms Smith", 35, "Computer Science");
Teacher t2 = new Teacher("Mr Jones", 42, "Mathematics");
Department cs = new Department("CS", 10);
cs.addTeacher(t1);
cs.printStaff();
t1 = Teacher("Ms Smith", 35, "Computer Science")
t2 = Teacher("Mr Jones", 42, "Mathematics")
cs = Department("CS", 10)
cs.add_teacher(t1)
cs.print_staff()
Output:
CS department:
Ms Smith (Computer Science)
ဒီဥပမာက ပုံစံ နှစ်မျိုးလုံးကို ပေါင်းထားပါတယ်:
- Inheritance:
TeacherIS-APerson(extends) - Aggregation:
Departmentမှာ ဆရာတွေ ရှိပါတယ် (HAS)၊ ဆရာတွေက သီးခြား ရှိနေပါတယ်
Quick Check (အမြန် စစ်ဆေးမေးခွန်း)
Q1. OOP (object တွေကို အခြေခံပြီး program ရေးနည်း) မှာ composition ဆိုတာ ဘာလဲ။
Q2. Composition နဲ့ aggregation ရဲ့ အဓိက ကွာခြားချက်က ဘာလဲ။
Q3. Hospital (ဆေးရုံ) တစ်ခုမှာ Room (အခန်း) object တွေနဲ့ Doctor (ဆရာဝန်) object တွေ ပါပါတယ်။ အခန်းတွေက ဆေးရုံ မရှိရင် မရှိနိုင်ပေမယ့် ဆရာဝန်တွေကတော့ ရှိနိုင်ပါတယ်။ ဘယ်ဟာက composition ဖြစ်ပြီး ဘယ်ဟာက aggregation လဲ။
Q4. "favour composition over inheritance" ဆိုတာ ဘာကို ဆိုလိုသလဲ။
Q5. ကျောင်းသား တစ်ယောက်က class Stack extends ArrayList လို့ ရေးပါတယ်။ ဒါ ဘာကြောင့် ညံ့တဲ့ design ဖြစ်တာလဲ။
Trace Exercise (code ကို တစ်ဆင့်ချင်း လိုက်ကြည့်ခြင်း)
Object ဆက်နွယ်မှုတွေကို trace (တစ်ဆင့်ချင်း လိုက်ပြီး မှတ်) လုပ်ပါ။ Author ကို တစ်ကြိမ်ပဲ ဖန်တီးပြီး Book object နှစ်ခုက မျှသုံးပါတယ်။ အဖြေတွေကို code ထဲကအတိုင်း English လို ရိုက်ထည့်ပါ။
Trace: Aggregation ဆက်နွယ်မှုများ
Author a = new Author("Orwell", "British");
Book b1 = new Book("1984", a, 328);
Book b2 = new Book("Animal Farm", a, 112);| Variable | Type | describe() ရဲ့ output |
|---|---|---|
| b1 | ||
| b2 |
b1 နဲ့ b2 က Author object တစ်ခုတည်းကို မျှသုံးသလား။ yes (ဟုတ်တယ်) ဒါမှမဟုတ် no (မဟုတ်ဘူး) လို့ ရိုက်ပါ:
စာအုပ် နှစ်အုပ်လုံးက Author object တစ်ခုတည်းကို ညွှန်းပါတယ်။ ဒါက aggregation ပါ: Author က သီးခြား ရှိနေပြီး မျှသုံးခံရပါတယ်။
Spot the Error (အမှား ရှာခြင်း)
ကျောင်းသား တစ်ယောက်က စာသင်ခန်း (classroom) တိုင်းမှာ desk (စာရေးခုံ) တွေ ရှိတဲ့ ကျောင်း တစ်ခုကို model လုပ်ဖို့ ကြိုးစားပါတယ်။ သူက composition အစား inheritance ကို သုံးလိုက်ပါတယ်။
အမှား ရှာပါ: စာသင်ခန်းတွေထဲမှာ desk တွေ ပါတဲ့ ကျောင်း စနစ် တစ်ခုပါ။ ကျောင်းသားက ဆက်နွယ်မှု အမျိုးအစား မှားတာကို သုံးထားပါတယ်။
Line 1 အတွက် မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ:
Predict the Output (output ကို ကြိုခန့်မှန်းခြင်း)
အဓိက အယူအဆများ အပိုင်းက Car နဲ့ Engine class တွေကို သုံးပါ။ ဒီ code က ဘာကို print ထုတ်မလဲ။
Car c = new Car("Honda Civic", 150);
c.drive();Line နှစ်ကြောင်းလုံးကို \n နဲ့ ခြားပြီး ရိုက်ထည့်ပါ:
Practice Exercises (လေ့ကျင့်ခန်းများ)
Core (အခြေခံ အဆင့်)
- ဆက်နွယ်မှုတွေကို ခွဲခြားပါ: အတွဲ တစ်တွဲစီအတွက် ဆက်နွယ်မှုက inheritance (is-a)၊ composition (has-a၊ lifecycle ချင်း မှီခိုတယ်) ဒါမှမဟုတ် aggregation (has-a၊ သီးခြား ရှိနေနိုင်တယ်) ဖြစ်လား ဆုံးဖြတ်ပါ:
- (a) University (တက္ကသိုလ်) နဲ့ Department (ဌာန)
- (b) Dog နဲ့ Animal
- (c) Playlist နဲ့ Song (သီချင်း)
- (d) Spreadsheet နဲ့ Cell (ဇယားကွက်)
- (e) Manager နဲ့ Employee (ဝန်ထမ်း)
- (f) Library နဲ့ Shelf (စာအုပ်စင်)၊ ဒီမှာ
Libraryobject က သူ့Shelfobject တွေကို ကိုယ်တိုင် ဖန်တီးပြီး Shelf တွေက Library မရှိရင် မရှိနိုင်ပါဘူး
- Composition နဲ့ တည်ဆောက်ပါ:
Batteryobject (capacityနဲ့charge()method ပါတယ်) တစ်ခုနဲ့Screenobject (sizeနဲ့display(String message)method ပါတယ်) တစ်ခု ပါဝင်တဲ့Phoneclass တစ်ခု ဖန်တီးပါ။ Phone မှာ battery ကို charge လုပ်ပြီး message တစ်ခု ပြပေးတဲ့use()method ပါရပါမယ်။
Extension (တိုးချဲ့ အဆင့်)
-
Inheritance ကို composition အဖြစ် refactor လုပ်ပါ: ကျောင်းသား တစ်ယောက်က
class ElectricCar extends Batteryလို့ ရေးထားပါတယ်။ ဒါ ဘာကြောင့် မှားလဲဆိုတာ Explain (ရှင်းပြပါ) လုပ်ပြီးElectricCarကCarကို extend လုပ်ကာBatteryကို HAS-A ဖြစ်အောင် composition သုံးပြီး ပြန်ရေးပါ (refactor: code ရဲ့ ရလဒ် မပြောင်းဘဲ ပုံစံကို ပြင်ရေးခြင်း)။ -
Trade-off (တစ်ခု ရဖို့ တစ်ခု အလျှော့ပေးရတာ) တွေကို ရှင်းပြပါ: Game တစ်ခုမှာ
Warrior,Mageနဲ့Archerclass တွေ ရှိပါတယ်။ တစ်ခုစီမှာ ကစားနေစဉ် လဲလို့ရတဲ့Weapon(လက်နက်) တစ်ခု ရှိပါတယ်။Weaponက parent class (inheritance) ဖြစ်သင့်သလား၊ attribute (composition) ဖြစ်သင့်သလား။ အကြောင်းပြချက် အနည်းဆုံး နှစ်ခုနဲ့ ကိုယ့်အဖြေကို Justify (ဘာကြောင့် ရွေးတာလဲ အကြောင်းပြချက်နဲ့ ပြပါ) လုပ်ပါ။
Challenge (စိန်ခေါ်မှု အဆင့်)
- စားသောက်ဆိုင် စနစ်: Composition နဲ့ aggregation ပါတဲ့ စားသောက်ဆိုင် order မှာတဲ့ စနစ် တစ်ခုကို Design (အစီအစဉ် ဒါမှမဟုတ် model တစ်ခု ရေးဆွဲပါ) လုပ်ပါ။
RestaurantမှာMenuitem တွေ ရှိပါတယ် (composition: menu က restaurant ရဲ့ ပိုင်ဆိုင်မှုပါ)။OrderမှာMenuItemreference တွေ ရှိပါတယ် (aggregation: menu item တစ်ခုတည်းက order အများမှာ ပါနိုင်ပါတယ်)။ Class အားလုံးကို သင့်တော်တဲ့ constructor တွေနဲ့ ဖန်တီးပါ။ Order တစ်ခုရဲ့ စုစုပေါင်း ဈေးနှုန်းကို return (ရလဒ်အဖြစ် ပြန်ပေး) လုပ်တဲ့calculateTotal()method ကို ရေးပါ။
ဆက်စပ် ခေါင်းစဉ်များ
- အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Aggregation: SL အဆင့် ဥပမာတွေနဲ့ has-a ဆက်နွယ်မှုများ
- အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Inheritance (parent class ကနေ အမွေဆက်ခံခြင်း): extends ကို သုံးတဲ့ is-a ဆက်နွယ်မှုများ
- အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Abstract Classes (object တိုက်ရိုက် မဖန်တီးနိုင်တဲ့ class များ) နဲ့ Interfaces (class တစ်ခု implement လုပ်ရမယ့် method စာရင်းများ): inheritance အစား သုံးနိုင်တဲ့ နည်းလမ်းများ
- ဆက်စပ် ခေါင်းစဉ်: Encapsulation (ဒေတာနဲ့ method ကို တစ်စုတည်း ထုပ်ပိုးခြင်း): composition က အတွင်းက object တွေကို ဖုံးထားပေးလို့ encapsulation ကို လိုက်နာစေပါတယ်
- ဆက်စပ် ခေါင်းစဉ်: UML Class Diagrams (class တစ်ခုကို အကွက် သုံးကွက်နဲ့ ပြတဲ့ ပုံများ): composition ကို အပြည့်ခြယ်ထားတဲ့ စိန်ပုံနဲ့၊ aggregation ကို အလွတ် စိန်ပုံနဲ့ ပြပါတယ်