Interfaces (class တစ်ခု implement လုပ်ရမယ့် method စာရင်းများ)

B3.2 (HL): Use interfaces to define contracts that classes must implement.
မြန်မာလို: class (object တွေ ဖန်တီးဖို့ ပုံစံခွက်) တွေ implement (တကယ် အလုပ်လုပ်အောင် ရေး) လုပ်ရမယ့် contract (လိုက်နာရမယ့် သဘောတူချက်) တွေကို သတ်မှတ်ဖို့ interface (class တစ်ခု implement လုပ်ရမယ့် method စာရင်း) တွေကို သုံးနိုင်ရပါမယ်။

ဒီစာမျက်နှာက HL အဆင့်မှာပဲ စစ်ဆေးတဲ့ အကြောင်းအရာ ဖြစ်ပါတယ်။ SL (Standard Level) နဲ့ HL (Higher Level) ဆိုတာ IB Computer Science (နိုင်ငံတကာ ကျောင်းတွေမှာ သင်တဲ့ ကွန်ပျူတာသိပ္ပံ သင်ရိုး) သင်တန်းရဲ့ အဆင့်နှစ်ဆင့် ဖြစ်ပြီး HL အပိုင်းတွေက ပိုနက်နက်ရှိုင်းရှိုင်း လေ့လာရတဲ့ အပိုင်းတွေပါ။


အဓိက အယူအဆများ

Interface ဆိုတာ ဘာလဲ

Interface က contract တစ်ခုကို သတ်မှတ်ပါတယ်: အဲဒါကို implement လုပ်တဲ့ class တိုင်း ရေးပေးရမယ့် method (သီးခြား အလုပ်တစ်ခု လုပ်ပေးတဲ့ code အပိုင်း) signature (method ရဲ့ နာမည်နဲ့ parameter type တွေ) အစုပါ။ Class တစ်ခုက ဘာ လုပ်နိုင်လဲ ဆိုတာကို သတ်မှတ်ပေးပြီး ဘယ်လို လုပ်လဲ ဆိုတာကိုတော့ မသတ်မှတ်ပါဘူး။

public interface Drawable {
    void draw();
    String getDescription();
}
# Python has no interface keyword. The closest simple equivalent is a plain class
# of method stubs: Python relies on convention (duck typing) where Java enforces a contract.
class Drawable():
    def draw(self):
        raise NotImplementedError

    def get_description(self):
        raise NotImplementedError

Interface ထဲမှာ ဒါတွေပဲ ပါပါတယ်:

  • Abstract method (body မပါဘဲ ကြေညာချက်ပဲ ပါတဲ့ method) signature တွေ (method body (method ထဲမှာ ရေးထားတဲ့ code) တွေ မပါပါ)
  • Constant (ပြောင်းလို့ မရတဲ့ တန်ဖိုး) တွေ (default (သတ်မှတ်မထားရင် သုံးတဲ့) အနေနဲ့ public static final ဖြစ်ပါတယ်)

Constructor (object ဖန်တီးချိန် attribute တွေကို စတင် သတ်မှတ်ပေးတဲ့ method)၊ instance variable (object တစ်ခုချင်းရဲ့ ကိုယ်ပိုင် variable) နဲ့ method implementation (တကယ် အလုပ်လုပ်အောင် ရေးထားတဲ့ code) တွေ လုံးဝ မပါပါဘူး။

ဒီစာမျက်နှာနဲ့ လက်ရှိ IB Computer Science သင်ရိုးက interface ကို ဒီလို သတ်မှတ်ပါတယ်၊ စာမေးပွဲ အဖြေတွေမှာ သုံးရမယ့် အဓိပ္ပာယ်လည်း ဒါပါပဲ။ Java version အသစ်တွေမှာတော့ interface ထဲမှာ default method body တစ်ခု ထည့်ထားခွင့် ရှိပြီး implement လုပ်တဲ့ class တွေက အဲဒါကို အမွေရပါတယ်။ ဒါကို library (အသင့်ရေးထားပြီး ယူသုံးလို့ရတဲ့ code အစု) code တွေမှာ တွေ့ရပါလိမ့်မယ်၊ အောက်က နှိုင်းယှဉ်ဇယားမှာ ဒါက ဘယ်နေရာမှာ ကွာခြားမှုကို ပြောင်းစေလဲ ဆိုတာ မှတ်ထားပါတယ်။

Interface ကို Implement လုပ်ခြင်း

Class တစ်ခုက interface တစ်ခုကို လက်ခံ လိုက်နာဖို့ implements keyword (programming language မှာ အထူး အဓိပ္ပာယ်ရှိတဲ့ စကားလုံး) ကို သုံးပါတယ်။ ပြီးရင် interface ထဲမှာ ကြေညာထားတဲ့ method တိုင်းအတွက် body ကို ရေးပေးရပါမယ်:

public class Circle implements Drawable {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public void draw() {
        System.out.println("Drawing a circle with radius " + radius);
    }

    @Override
    public String getDescription() {
        return "Circle (r=" + radius + ")";
    }
}

public class TextBox implements Drawable {
    private String text;

    public TextBox(String text) {
        this.text = text;
    }

    @Override
    public void draw() {
        System.out.println("Rendering text: " + text);
    }

    @Override
    public String getDescription() {
        return "TextBox: " + text;
    }
}
class Circle(Drawable):    # "implements" = inherit from the stub class
    def __init__(self, radius):
        self._radius = radius

    def draw(self):
        print("Drawing a circle with radius", self._radius)

    def get_description(self):
        return "Circle (r=" + str(self._radius) + ")"

class TextBox(Drawable):
    def __init__(self, text):
        self._text = text

    def draw(self):
        print("Rendering text:", self._text)

    def get_description(self):
        return "TextBox: " + self._text

Class တစ်ခုက implements Drawable လို့ ရေးထားပေမယ့် draw() နဲ့ getDescription() ကို ရေးမထားရင် compiler (code တစ်ခုလုံးကို ကြိုတင် ဘာသာပြန်တဲ့ program) က compile error (compile လုပ်ချိန်မှာ ဖြစ်တဲ့ error) ပြပါတယ်။ (Python မှာ ဒီလို စစ်ဆေးမှု မရှိပါဘူး: ရေးဖို့ မေ့ခဲ့တဲ့ method က runtime (program run နေစဉ်) မှာ ပထမဆုံး ခေါ်တဲ့အခါမှပဲ error ဖြစ်ပါတယ်။)

Interface ဆိုတာ ကတိ တစ်ခုပါ။ Class တစ်ခုက interface ကို implement လုပ်ရင် interface ကြေညာထားတဲ့ method အားလုံးကို ရေးပေးမယ်လို့ အာမခံပါတယ်။ တခြား code တွေက အဲဒီ class အတိအကျကို မသိဘဲနဲ့ ဒီ အာမခံချက်ကို အားကိုးလို့ ရပါတယ်။

Interface ကို Type အဖြစ် သုံးခြင်း

Abstract class (object တိုက်ရိုက် မဖန်တီးနိုင်တဲ့ class) တွေလိုပဲ interface တွေကိုလည်း variable (တန်ဖိုး သိမ်းထားတဲ့ နာမည်ပေးထားတဲ့ နေရာ)၊ parameter (method ကို ပေးလိုက်တဲ့ တန်ဖိုးကို လက်ခံတဲ့ variable) နဲ့ array (အရွယ်အစား ပုံသေ၊ အမျိုးအစားတူ ဒေတာစု) တွေရဲ့ type (အမျိုးအစား) အဖြစ် သုံးလို့ ရပါတယ်:

Drawable[] canvas = new Drawable[3];
canvas[0] = new Circle(5);
canvas[1] = new TextBox("Hello");
canvas[2] = new Circle(3);

for (int i = 0; i < canvas.length; i++) {
    System.out.println(canvas[i].getDescription());
    canvas[i].draw();
}
canvas = []
canvas.append(Circle(5.0))    # .0 mirrors Java's double, so "r=5.0" prints
canvas.append(TextBox("Hello"))
canvas.append(Circle(3.0))

for i in range(len(canvas)):
    print(canvas[i].get_description())
    canvas[i].draw()

Output (program က ထုတ်ပြတဲ့ ရလဒ်):

Circle (r=5.0)
Drawing a circle with radius 5.0
TextBox: Hello
Rendering text: Hello
Circle (r=3.0)
Drawing a circle with radius 3.0

Loop (ထပ်ခါထပ်ခါ run တဲ့ code အပိုင်း) က element (အစုထဲက အချက်) တစ်ခုစီဟာ Circle လား TextBox လား ဆိုတာကို မသိသလို ဂရုလည်း မစိုက်ပါဘူး။ Element တစ်ခုစီက Drawable ဖြစ်တယ်၊ ဒါကြောင့် draw() နဲ့ getDescription() ပါတယ် ဆိုတာကိုပဲ သိပါတယ်။

Interface အများ

Class တစ်ခုက interface အများ ကို implement လုပ်နိုင်ပါတယ်။ ဒါက inheritance (parent class ကနေ အမွေဆက်ခံခြင်း) ထက် အဓိက သာတဲ့ အချက်ပါ၊ inheritance မှာတော့ class တစ်ခုက parent တစ်ခုကိုပဲ extend (အမွေဆက်ခံ) လုပ်နိုင်ပါတယ်:

public interface Printable {
    void print();
}

public interface Saveable {
    void save(String filename);
}

public class Document implements Printable, Saveable {
    private String content;

    public Document(String content) {
        this.content = content;
    }

    @Override
    public void print() {
        System.out.println("Printing: " + content);
    }

    @Override
    public void save(String filename) {
        System.out.println("Saving to " + filename);
    }
}
# Python has no implements keyword - a class can simply inherit from BOTH stub
# classes (Python allows multiple inheritance; a Java class cannot extend two classes)
class Printable():
    def print(self):
        raise NotImplementedError

class Saveable():
    def save(self, filename):
        raise NotImplementedError

class Document(Printable, Saveable):
    def __init__(self, content):
        self._content = content

    def print(self):
        print("Printing:", self._content)

    def save(self, filename):
        print("Saving to", filename)

Document က Printable ရော Saveable ပါ implement လုပ်ပါတယ်။ အခြေအနေပေါ် မူတည်ပြီး Printable[] array ထဲမှာ ဒါမှမဟုတ် Saveable[] array ထဲမှာ သိမ်းလို့ ရပါတယ်။ Single inheritance (parent class တစ်ခုတည်းကနေပဲ အမွေဆက်ခံခြင်း) တစ်ခုတည်းနဲ့ဆိုရင် ဒီလို ပြောင်းလွယ်ပြင်လွယ် ရှိဖို့ မဖြစ်နိုင်ပါဘူး။

Java က single inheritance (extends တစ်ခုတည်း) ကိုပဲ ခွင့်ပြုပေမယ့် interface အများကို implement လုပ်တာ (implements အများ) ကိုတော့ ခွင့်ပြုပါတယ်။ Java က multiple inheritance (parent class အများကနေ အမွေဆက်ခံခြင်း) ရဲ့ အကျိုးကျေးဇူးတွေကို ရှုပ်ထွေးမှု မပါဘဲ ဒီနည်းနဲ့ ပေးပါတယ်။

Interface နဲ့ Inheritance ကို ပေါင်းသုံးခြင်း

Class တစ်ခုက parent class (အမွေပေးတဲ့ class) တစ်ခုကို extend လုပ်တာ ရော interface တစ်ခု ဒါမှမဟုတ် တစ်ခုထက်ပိုပြီး implement လုပ်တာ ပါ တစ်ပြိုင်နက် လုပ်နိုင်ပါတယ်:

public abstract class Shape {
    private String colour;

    public Shape(String colour) {
        this.colour = colour;
    }

    public String getColour() { return colour; }
    public abstract double getArea();
}

public class Circle extends Shape implements Drawable {
    private double radius;

    public Circle(String colour, double radius) {
        super(colour);
        this.radius = radius;
    }

    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }

    @Override
    public void draw() {
        System.out.println("Drawing " + getColour() + " circle");
    }

    @Override
    public String getDescription() {
        return getColour() + " circle (r=" + radius + ")";
    }
}
import math

class Shape():
    def __init__(self, colour):
        self._colour = colour

    def get_colour(self):
        return self._colour

    def get_area(self):
        raise NotImplementedError    # "abstract" - Python has no abstract keyword

class Circle(Shape, Drawable):    # inherit the parent class AND the contract class
    def __init__(self, colour, radius):
        super().__init__(colour)    # call the parent (Shape) constructor
        self._radius = radius

    def get_area(self):
        return math.pi * self._radius * self._radius

    def draw(self):
        print("Drawing", self.get_colour(), "circle")

    def get_description(self):
        return self.get_colour() + " circle (r=" + str(self._radius) + ")"

Circle က Shape ကနေ အမွေဆက်ခံပါတယ် (colour ကို ရပြီး getArea() ကို ရေးဖို့ လိုပါတယ်)၊ ပြီးတော့ Drawable ကို implement လုပ်ပါတယ် (draw() နဲ့ getDescription() ကို ရေးဖို့ လိုပါတယ်)။ extends အပိုင်းက implements ရဲ့ ရှေ့မှာ လာပါတယ်။ (Python မှာတော့ အလုပ် နှစ်ခုလုံးအတွက် syntax (code ရေးထုံး) တူတူပဲ သုံးပါတယ်: class header ရဲ့ ကွင်းထဲမှာ parent class နဲ့ contract class ကို တွဲရေးပါတယ်။)

Interface နဲ့ Abstract Class နှိုင်းယှဉ်ချက်

အချက် Abstract Class Interface
Keyword abstract class interface
ယူသုံးပုံ extends (တစ်ခုတည်းပဲ) implements (အများ ရပါတယ်)
Constructor ရှိပါတယ် မရှိပါ
Instance variable ရှိပါတယ် မရှိပါ (constant တွေပဲ)
Concrete (abstract မဟုတ်တဲ့ ပုံမှန်) method ရှိပါတယ် (မျှသုံးတဲ့ လုပ်ဆောင်ပုံ) မရှိပါ (signature တွေပဲ၊ Java အသစ်တွေမှာ default method body တွေ ထားခွင့် ရှိပေမယ့် syllabus မှာ မပါပါဘူး)
Abstract method ရှိပါတယ် (တချို့ ဒါမှမဟုတ် အားလုံး) Method အားလုံး abstract ပါ
ဘယ်အချိန် သုံးမလဲ Class တွေမှာ တူညီတဲ့ state (attribute တွေမှာ လက်ရှိ ရှိနေတဲ့ တန်ဖိုးများ) နဲ့ behaviour (object က လုပ်နိုင်တာတွေ) ရှိတဲ့အခါ ဆက်စပ်မှု မရှိတဲ့ class တွေမှာ စွမ်းရည် တူတူ ရှိတဲ့အခါ

Abstract class ကို ဘယ်အချိန် သုံးမလဲ:

  • Subclass (အမွေဆက်ခံတဲ့ child class) တွေက attribute (object ရဲ့ ဒေတာကို သိမ်းတဲ့ variable) တွေနဲ့ concrete method တွေကို မျှသုံးတဲ့အခါ (ဥပမာ name, age, getName() ပါတဲ့ Animal)
  • ရှင်းလင်းတဲ့ is-a (X က Y တစ်မျိုး ဖြစ်တယ် ဆိုတဲ့ ဆက်နွယ်မှု) hierarchy (parent နဲ့ child class တွေကို အဆင့်ဆင့် ဖွဲ့ထားတဲ့ ပုံစံ) ရှိတဲ့အခါ

Interface ကို ဘယ်အချိန် သုံးမလဲ:

  • ဆက်စပ်မှု မရှိတဲ့ class အများမှာ တူညီတဲ့ စွမ်းရည် လိုတဲ့အခါ (ဥပမာ Drawable, Comparable, Serializable)
  • Class တစ်ခုက contract အများ နဲ့ ကိုက်ညီဖို့ လိုတဲ့အခါ

Abstract class ကို “တစ်ခုခုက ဘာ ဖြစ် လဲ” လို့၊ interface ကို “တစ်ခုခုက ဘာ လုပ်နိုင် လဲ” လို့ မှတ်ထားပါ။ Dog က Animal ဖြစ် ပါတယ် (abstract class)၊ ဒါပေမယ့် Dog က Trainable ဖြစ်နိုင် ပါတယ်၊ ဆိုလိုတာက လေ့ကျင့်ပေးလို့ ရပါတယ် (interface)။


အဆင့်ဆင့် ရှင်းပြထားတဲ့ ဥပမာများ

ဥပမာ 1: နှိုင်းယှဉ်လို့ရတဲ့ Item များ

ကျောင်းသုံး app တစ်ခုက ကျောင်းဆိုင်ထဲက ကုန်ပစ္စည်း (product) တွေနဲ့ ကျောင်းသားတွေကို တစ်မျိုးချင်း မတူတဲ့ စံနှုန်းတွေနဲ့ စီဖို့ လိုပါတယ်။ နှစ်မျိုးလုံးကို နှိုင်းယှဉ်လို့ ရပေမယ့် လုံးဝ မဆိုင်တဲ့ class တွေပါ။

public interface Sortable {
    int getSortKey();
}

public class Product implements Sortable {
    private String name;
    private double price;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() { return name; }
    public double getPrice() { return price; }

    @Override
    public int getSortKey() {
        return (int) (price * 100);  // sort by price in cents
    }
}

public class Student implements Sortable {
    private String name;
    private int score;

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    public String getName() { return name; }
    public int getScore() { return score; }

    @Override
    public int getSortKey() {
        return score;  // sort by score
    }
}
# The "interface" is a stub class - the real contract is the shared method name
class Sortable():
    def get_sort_key(self):
        raise NotImplementedError

class Product(Sortable):
    def __init__(self, name, price):
        self._name = name
        self._price = price

    def get_name(self):
        return self._name

    def get_price(self):
        return self._price

    def get_sort_key(self):
        return int(self._price * 100)    # sort by price in cents

class Student(Sortable):
    def __init__(self, name, score):
        self._name = name
        self._score = score

    def get_name(self):
        return self._name

    def get_score(self):
        return self._score

    def get_sort_key(self):
        return self._score    # sort by score

Sort method တစ်ခုတည်းက ဘယ် Sortable array မှာမဆို အလုပ်လုပ်ပါတယ်:

// Selection sort that works on ANY Sortable objects
public static void sort(Sortable[] items) {
    for (int i = 0; i < items.length - 1; i++) {
        int minIndex = i;
        for (int j = i + 1; j < items.length; j++) {
            if (items[j].getSortKey() < items[minIndex].getSortKey()) {
                minIndex = j;
            }
        }
        Sortable temp = items[minIndex];
        items[minIndex] = items[i];
        items[i] = temp;
    }
}
# Selection sort that works on ANY objects with get_sort_key() -
# duck typing: Python never checks the type, only that the method exists
def sort(items):
    for i in range(len(items) - 1):
        min_index = i
        for j in range(i + 1, len(items)):
            if items[j].get_sort_key() < items[min_index].get_sort_key():
                min_index = j
        temp = items[min_index]
        items[min_index] = items[i]
        items[i] = temp
Product[] products = {
    new Product("Laptop", 999.99),
    new Product("Mouse", 29.99),
    new Product("Keyboard", 79.99)
};
sort(products);

for (int i = 0; i < products.length; i++) {
    System.out.println(products[i].getName() + ": $" + products[i].getPrice());
}
products = [
    Product("Laptop", 999.99),
    Product("Mouse", 29.99),
    Product("Keyboard", 79.99)
]
sort(products)

for i in range(len(products)):
    print(products[i].get_name() + ": $" + str(products[i].get_price()))

Output:

Mouse: $29.99
Keyboard: $79.99
Laptop: $999.99

sort() method က Product ကိုလည်း Student ကိုလည်း မသိပါဘူး။ Sortable interface ရဲ့ contract ကိုပဲ အားကိုးပါတယ်။

ဥပမာ 2: Interface အများ

စက်ပစ္စည်းတွေကို ထိန်းချုပ်လို့လည်း ရ၊ စောင့်ကြည့်လို့လည်း ရတဲ့ smart home စနစ် တစ်ခုပါ။

public interface Controllable {
    void turnOn();
    void turnOff();
    boolean isOn();
}

public interface Monitorable {
    String getStatus();
}

public class SmartLight implements Controllable, Monitorable {
    private String room;
    private boolean on;

    public SmartLight(String room) {
        this.room = room;
        this.on = false;
    }

    @Override
    public void turnOn() { on = true; }

    @Override
    public void turnOff() { on = false; }

    @Override
    public boolean isOn() { return on; }

    @Override
    public String getStatus() {
        return room + " light: " + (on ? "ON" : "OFF");
    }
}

public class Thermostat implements Controllable, Monitorable {
    private double temperature;
    private boolean on;

    public Thermostat(double temperature) {
        this.temperature = temperature;
        this.on = false;
    }

    @Override
    public void turnOn() { on = true; }

    @Override
    public void turnOff() { on = false; }

    @Override
    public boolean isOn() { return on; }

    @Override
    public String getStatus() {
        String state = on ? "heating to " + temperature + "C" : "OFF";
        return "Thermostat: " + state;
    }
}
# Two "interfaces" as stub classes - the contract is enforced by convention only
class Controllable():
    def turn_on(self):
        raise NotImplementedError

    def turn_off(self):
        raise NotImplementedError

    def is_on(self):
        raise NotImplementedError

class Monitorable():
    def get_status(self):
        raise NotImplementedError

class SmartLight(Controllable, Monitorable):
    def __init__(self, room):
        self._room = room
        self._on = False

    def turn_on(self):
        self._on = True

    def turn_off(self):
        self._on = False

    def is_on(self):
        return self._on

    def get_status(self):
        if self._on == True:    # Java's on ? "ON" : "OFF" becomes a plain if/else
            return self._room + " light: ON"
        else:
            return self._room + " light: OFF"

class Thermostat(Controllable, Monitorable):
    def __init__(self, temperature):
        self._temperature = temperature
        self._on = False

    def turn_on(self):
        self._on = True

    def turn_off(self):
        self._on = False

    def is_on(self):
        return self._on

    def get_status(self):
        if self._on == True:
            state = "heating to " + str(self._temperature) + "C"
        else:
            state = "OFF"
        return "Thermostat: " + state
Controllable[] devices = {
    new SmartLight("Kitchen"),
    new Thermostat(22.0)
};

// Turn everything on
for (int i = 0; i < devices.length; i++) {
    devices[i].turnOn();
}

// Check status (need to cast to Monitorable)
for (int i = 0; i < devices.length; i++) {
    Monitorable m = (Monitorable) devices[i];
    System.out.println(m.getStatus());
}
devices = [
    SmartLight("Kitchen"),
    Thermostat(22.0)
]

# Turn everything on
for i in range(len(devices)):
    devices[i].turn_on()

# Check status - Python needs NO cast: if the object has get_status(), the call works
for i in range(len(devices)):
    print(devices[i].get_status())

Output:

Kitchen light: ON
Thermostat: heating to 22.0C

SmartLight ရော Thermostat ပါ interface နှစ်ခုကို implement လုပ်ပါတယ်။ Code က ဘာလိုလဲ ဆိုတာပေါ် မူတည်ပြီး သူတို့ကို Controllable (ဖွင့်ဖို့၊ ပိတ်ဖို့) အဖြစ် ဒါမှမဟုတ် Monitorable (status စစ်ဖို့) အဖြစ် ဆက်ဆံလို့ ရပါတယ်။


Quick Check (အမြန် စစ်ဆေးမေးခွန်း)

Q1. Interface ထဲမှာ ဘာတွေ ပါသလဲ။

Q2. Class တစ်ခုက interface ဘယ်နှစ်ခုကို implement လုပ်နိုင်သလဲ။

Q3. Class တစ်ခုက Drawable ကို implement လုပ်ပေမယ့် draw() method ကို ရေးမထားပါဘူး။ ဘာဖြစ်မလဲ။

Q4. Abstract class အစား interface ကို ဘယ်အချိန်မှာ သုံးသင့်သလဲ။

Q5. Class တစ်ခုကို extend လုပ်တာ ရော interface တစ်ခုကို implement လုပ်တာ ပါ တစ်ပြိုင်နက် ရေးတဲ့ မှန်ကန်တဲ့ syntax က ဘာလဲ။


Trace Exercise (code ကို တစ်ဆင့်ချင်း လိုက်ကြည့်ခြင်း)

Interface method call (method ကို ခေါ်သုံးခြင်း) တွေကို trace (တစ်ဆင့်ချင်း လိုက်ပြီး မှတ်) လုပ်ပါ။ SmartLight နဲ့ Thermostat နှစ်ခုလုံးက Controllable နဲ့ Monitorable ကို implement လုပ်ပါတယ်။ အဖြေတွေကို code ရဲ့ တန်ဖိုးနဲ့ output အတိုင်း English လို ရိုက်ထည့်ပါ (ဥပမာ true, false)။

Trace: Interface ကနေ method ခေါ်ပုံ

SmartLight light = new SmartLight("Living Room");
Thermostat thermo = new Thermostat(21.5);

light.turnOn();
thermo.turnOn();
thermo.turnOff();
စက်ပစ္စည်းisOn()getStatus()
light
thermo

Thermostat ကို on လုပ်ပြီးနောက် ပြန် off လုပ်ထားပါတယ်။ နောက်ဆုံး state က off ပါ။


Spot the Error (အမှား ရှာခြင်း)

ဒီ code က interface တစ်ခုနဲ့ အဲဒါကို implement လုပ်ရမယ့် class တစ်ခုကို သတ်မှတ်ထားပါတယ်။ အမှားကို ရှာပါ။

အမှား ရှာပါ: Media player interface တစ်ခုပါ။ AudioPlayer class က play(), stop() နဲ့ pause() ကို ကြေညာထားတဲ့ Playable ထဲက method အားလုံးကို implement လုပ်ရပါမယ်။

1public interface Playable { 2 void play(); 3 void stop(); 4 void pause(); 5} 6 7public class AudioPlayer implements Playable { 8 // missing pause() implementation 9 public void play() { System.out.println("Playing"); } 10 public void stop() { System.out.println("Stopped"); } 11}

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


Predict the Output (output ကို ကြိုခန့်မှန်းခြင်း)

အဓိက အယူအဆများ အပိုင်းက Drawable interface ကို သုံးပါ။ အဲဒီမှာ Circle.getDescription() က "Circle (r=" + radius + ")" ကို၊ TextBox.getDescription() က "TextBox: " + text ကို return ပြန်ပေးပါတယ်။ ဒီ code က ဘာကို print ထုတ်မလဲ။

Drawable[] canvas = new Drawable[2];
canvas[0] = new Circle(5);
canvas[1] = new TextBox("Hello");
System.out.println(canvas[0].getDescription());
System.out.println(canvas[1].getDescription());

Line နှစ်ကြောင်းလုံးကို \n နဲ့ ခြားပြီး ရိုက်ထည့်ပါ:


Practice Exercises (လေ့ကျင့်ခန်းများ)

Core (အခြေခံ အဆင့်)

  1. Measurable interface: double getMeasurement() method ပါတဲ့ Measurable interface တစ်ခု ဖန်တီးပါ။ Class နှစ်ခု ဖန်တီးပါ: Ruler (သူ့ အရှည်ကို cm နဲ့ return ပြန်ပေးတယ်) နဲ့ Thermometer (လက်ရှိ အပူချိန်ကို return ပြန်ပေးတယ်)။ နှစ်ခုလုံးကို Measurable[] array ထဲမှာ သိမ်းပြီး တိုင်းတာချက် တစ်ခုစီကို print ထုတ်ပါ။

  2. Interface type: Drawable[] items = new Drawable[3]; ကို ပေးထားပါတယ်။ items[0] = new Drawable(); က ဘာကြောင့် compile error ဖြစ်စေပြီး items[0] = new Circle(5); ကတော့ ဘာကြောင့် အလုပ်လုပ်လဲဆိုတာ explain (ရှင်းပြပါ) လုပ်ပါ (Circle က Drawable ကို implement လုပ်တယ်လို့ ယူဆပါ)။

Extension (တိုးချဲ့ အဆင့်)

  1. Interface နှစ်ခု: Readable (String read() ပါတယ်) နဲ့ Writable (void write(String data) ပါတယ်) interface တွေကို ဖန်တီးပါ။ နှစ်ခုလုံးကို implement လုပ်တဲ့ File class တစ်ခု ဖန်တီးပါ။ Readable ကိုပဲ implement လုပ်တဲ့ Keyboard class တစ်ခု ဖန်တီးပါ။ Interface type တွေကို polymorphic array (မတူတဲ့ class တွေရဲ့ object တွေကို type တစ်ခုတည်းနဲ့ အတူ သိမ်းထားတဲ့ array) တွေအတွက် သုံးပုံကို ပြပါ။

  2. Compare and contrast (တူတာနဲ့ ကွာတာကို နှိုင်းယှဉ်ပါ): Abstract Classes စာမျက်နှာက abstract Shape class ကို ShapeSpec လို့ ခေါ်တဲ့ interface အဖြစ် ပြန်ရေးပါ။ ဘာတွေ ဆုံးရှုံးသွားလဲ။ ဘာတွေ ရလာလဲ။ Shape တွေအတွက် ဘယ်နည်းက ပိုကောင်းလဲ၊ ဘာကြောင့်လဲ။

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

  1. Plugin စနစ်: String getName(), void execute() နဲ့ int getPriority() method တွေ ပါတဲ့ Plugin interface တစ်ခုကို Design (အစီအစဉ် ဒါမှမဟုတ် model တစ်ခု ရေးဆွဲပါ) လုပ်ပါ။ SpellChecker, WordCounter နဲ့ AutoSaver ဆိုတဲ့ concrete plugin (program ထဲ ထပ်ထည့်လို့ရတဲ့ သီးခြား အစိတ်အပိုင်း) သုံးခု ဖန်တီးပါ။ Plugin တွေကို array ထဲမှာ သိမ်းပြီး priority (ဦးစားပေး အဆင့်) အလိုက် စီကာ (အနိမ့်ဆုံး အရင်) အစဉ်အတိုင်း execute လုပ်ပေးတဲ့ PluginManager class ကို ရေးပါ။

ဆက်စပ် ခေါင်းစဉ်များ

  • အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Abstract Classes: interface တွေက abstraction (မလိုတဲ့ အသေးစိတ်ကို ဖယ်ပြီး အဓိကကိုပဲ ကြည့်ခြင်း) ကို ပိုပြီး ရှေ့ဆက်ပါတယ်
  • အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Polymorphism (ပုံစံ အမျိုးမျိုး ယူနိုင်ခြင်း): interface တွေက ဆက်စပ်မှု မရှိတဲ့ class တွေကြားမှာ polymorphism ကို ဖြစ်နိုင်စေပါတယ်
  • နောက်ထပ် လေ့လာမယ့် ခေါင်းစဉ်: Composition vs Inheritance: has-a (X ထဲမှာ Y ပါတယ် ဆိုတဲ့ ဆက်နွယ်မှု) နဲ့ is-a၊ tight coupling (class တွေ အချင်းချင်း အလွန် မှီခိုနေခြင်း)၊ composition (ပိုခိုင်မာတဲ့ has-a ဆက်နွယ်မှု) ကို ဦးစားပေးခြင်း
  • ဆက်စပ် ခေါင်းစဉ်: Encapsulation (ဒေတာနဲ့ method ကို တစ်စုတည်း ထုပ်ပိုးခြင်း): interface တွေက implementation ကို ဖုံးထားပေးလို့ encapsulation ကို လိုက်နာစေပါတယ်
  • ဆက်စပ် ခေါင်းစဉ်: UML Class Diagrams (class တစ်ခုကို အကွက် သုံးကွက်နဲ့ ပြတဲ့ ပုံများ): UML (class တွေကို ပုံနဲ့ ပြတဲ့ စံ ရေးဆွဲနည်း) မှာ interface တွေကို အစက်ချ မြှား (dashed arrow) တွေနဲ့ ပြပါတယ်

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