May 5, 2012

Class များနှင့် မျိုးရိုးဆက်ခံခြင်း

မျိုးရိုးဆက်ခံခြင်း

Java သည် Object Oriented ၏ သဘောတရားကို အခြေခံသော ပရိုဂရမ်မင်းဘာသာရပ် တစ်ခုဖြစ်၏။ OOP ၏ အခြေခံ သဘောတရား တစ်ခုဖြစ်သော မျိုးရိုးဆက်ခံခြင်းအား Java ဘာသာရပ်တွင် အသုံးပြု နိုင်ပါသည်။

Object Oriented ၏ သဘောတရားထဲတွင် Objectတစ်ခုအား အခြားသော Object တစ်ခုမှ ဆင့်ပွား၍ တည်ဆောက်နိုင်၏။ ဤကဲ့သို့ ဆင့်ပွားတည်ဆောက်ထားသော Object သည် မှုရင်း Object ၏ ပိုင်ဆိုင်မှု့များကို ဆက်လက်ပိုင်ဆိုင်နိုင်၏။ ဤကဲ့သို့ Object တစ်ခုကို အခြားသော Object တစ်ခုမှ ဆင့်ပွား တည်ဆောက်ခြင်းနှင့် မှုရင်း Object တစ်ခု၏ ပိုင်ဆိုင်မှု့များကို လက်ဆင့်ကမ်းပိုင်ဆိုင်နိုင်ခြင်း တို့ကို မျိုးရိုးဆက်ခံခြင်း ဟုခေါ်ဆိုပါသည်။

Java ပရိုဂရမ်မင်းဘာသာရပ်သည် Class အခြေခံ ပရိုဂရမ်မင်းဘာသာရပ် တစ်ခု ဖြစ်သောကြောင့် မျိုးရိုးဆက်ခံခြင်းကို Class အဆင့်တွင် ထည့်သွင်းထားပါသည်။ Class တစ်ခုသည် Object တစ်ခု၏ ပိုင်ဆိုင်သင့်သော အချက်အလက်များကို သတ်မှတ်ပေးရုံသာမှက၊ Object တစ်ခု၏ ပတ်သက်မှု့များကိုလည်း ဖော်ပြပေးနေပါသည်။


extends


မျိုးရိုးဆက်ခံခြင်း သဘောတရား၌ ပင်မမှုရင်း Class အား Super Class ဟု ခေါ်ဆို၍၊ Super Class မှ တဆင့် ဆင့်ပွားတည်ဆောက်ထားသော အမွေဆက်ခံယူမည့် Class အား Sub Class ဟု ခေါ်ဆိုပါသည်။ Java ဘာသာရပ်တွင် မျိုးရိုးဆက်ခံခြင်းကို extends စကားလုံးကို အသုံးပြု၍ ရေးသားနိုင်ပါသည်။
public class Test {

 public static void main(String[] args) {
  MySuper sup = new MySuper("Super Class");
  System.out.println("MySuper#getData -> " + sup.getData());
  
  MySub sub = new MySub("Sub Class");
  System.out.println("MySub#getData -> " + sub.getData());
  System.out.println("MySub#getSub_data -> " + sub.getSub_data());
 }
}

class MySuper {

 private Object data;
 
 public MySuper(Object data) {
  this.data = data;
 }
 
 public Object getData() {
  return this.data;
 }
 
}

class MySub extends MySuper {
 
 private Object sub_data;
 
 public MySub(Object data) {
  super(data);
  this.sub_data = String.valueOf(super.getData()).toUpperCase();
 }
 
 public Object getSub_data() {
  return this.sub_data;
 }
}

အထက်ပါ ကုဒ်များအတွင်းတွင် စာကြောင်း ၁၃မှစ၍ ၂၅အထိသည် MySuper ကလပ်စ် အကြောင်းကို ရေးသားထားပါသည်။ MySuper ကလပ်စ်တွင် data ကို ပိုင်ဆိုင်၍၊ getData ဖြင့် data ကို ရရှိနိုင်ပါသည်။

တဖန် စာကြောင်း ၂၇မှ ၃၈သည် MySub ကလပ်စ်ကို ရေးသားထားပါသည်။ MySub သည် MySuper ကို extends လုပ်ထားပါသဖြင့် MySuper ၏ အမွေကို ဆက်ခံထားသော Sub Class တစ်ခုဖြစ်ပါသည်။ MySub တွင် sub_data ကို ပိုင်ဆိုင်ပြီး၊ Constructor ထဲတွင် super.getData() ဖြင့် Super Class ၏ data ကို ရယူပြီး၊ String#toUpperCase လုပ်ဆောင်ချက်ဖြင့် စာလုံးအကြီးကို ပြောင်းကာ sub_data တွင်အစားထိုးပါသည်။ MySub#getSub_data လုပ်ဆောင်ချက်ကို အသုံးပြုခြင်းအားဖြင့် sub_data ကို ရရှိနိုင်ပါသည်။

အထက်ပါ ကုဒ်များအား ကွန်ပိုင်းလုပ်၍ အလုပ်ခိုင်းကြည့်ပါက ကွန်ဆိုးတွင် အောက်ပါအတိုင်း ဖော်ပြပေးနိုင်သည်ကို တွေ့ရပါလိမ့်မည်။

MySuper#getData -> Super Class
MySub#getData -> Sub Class
MySub#getSub_data -> SUB CLASS

စာကြောင်း ၈ ကိုကြည့်ပါက၊ MySub ၏ instance ဖြစ်သော sub မှတဆင့် MySuper မှ အမွေ ဆက်ခံထားသော getData လုပ်ဆောင်ချက်ကို ခေါ်ယူနေသည်ကို တွေ့ရပါမည်။ ဤနည်းအားဖြင့် ကလပ်စ်တစ်ခု၏ ပိုင်ဆိုင်မှု့နှင့် လုပ်ဆောင်ချက်များအား ပြန်လည်အသုံးချနိုင်ရန် မျိုးရိုးဆက်ခံခြင်း သဘောတရားကို အသုံးပြုနိုင်ကြောင်း သိရှိနိုင်မည် ဖြစ်ပါသည်။


final class

ကလပ်စ်များအား ရေးသားရာတွင် အချို့သော ကလပ်စ်များအား ဆင့်ပွား ကလပ်စ်များ ဆက်လက်၍ တည်ဆောက် ခွင့်မပြု လိုသောအခါမျိုး ရှိပါလိမ့်မည်။ ထိုအခါမျိုးတွင် final စာလုံးကို အသုံးပြု၍ ရေးသားနိုင်ပါသည်။ ဥပမာအားဖြင့် အထက်ပါ နမှုနာ၏ စာကြောင်း ၁၃အား အောက်ပါအတိုင်း ပြင်ရေးသားပြီး ကွန်ပိုင်းလုပ်ကြည့်ပါမည်။
final class MySuper {


MySuper အား final class အဖြစ်သတ်မှတ်ပြီး၊ ကွန်ပိုင်းလုပ်ကြည့်သောအခါ အထက်ပါအတိုင်း MySuper သည် final class ဖြစ်ပါသောကြောင့် မျိုးရိုးဆက်ခံခွင့် မရှိကြောင်း ကွန်ပိုင်း Error ကို ဖြစ်ပေါ်စေမည် ဖြစ်ပါသည်။

မှတ်ချက်။ ။ အသုံးပြုနေသော Locale မှာ Japanese ဖြစ်နေပါသဖြင့် ကွန်ပိုင်း Message များသည် ဂျပန်စာဖြစ်နေသည်ကို သီးခံခွင့်လွှတ်စေလိုပါသည်။



မျိုးရိုးဆက်ခံခြင်း၏ အကျိုးနှင့် အဆိုး


မျိုးရိုးဆက်ခံခြင်းကို အသုံးပြုပါက ကလပ်စ် အဆင့်တွင် ရေးသားထားသော ကုဒ်များအား ပြန်လည် အသုံးပြုနိုင်သည်ကို တွေ့ခဲ့ရပါသည်။ ပြန်စဉ်းစားမည် ဆိုပါက Object Oriented အတွေးအခေါ်များ စတင် ခေတ်စားလာခဲ့ရခြင်းမှာ၊ အိုင်တီလုပ်ငန်းများ တိုးတက်ခါစ အချိန်ဖြစ်ပါသည်။ လုပ်ငန်းခွင်များတွင် သူ့ထက်ငါအပြိုင် အိုင်တီနည်းပညာများကို ထည့်သွင်းအသုံးပြုလာခဲ့ကြရာတွင် စစ္စတမ်များအား ရေးသားနိုင်သူ ပညာရှင်များမှာ လိုအပ်သည်ထက် အလွန်နည်းပါးခဲ့ပါသည်။ ရေးသားနိုင်သူ အလွန်နည်းပါခဲ့သော ထိုအခါမျိုးတွင် စစ္စတမ်တစ်ခုရေးတိုင်း အသစ် ပြန်လည် ရေးသားနေရသည်ထက်၊ ရေးပြီးသား ကုဒ်များအား ပြန်လည်အသုံးပြုနိုင်ရန် လိုအပ်လာခဲ့ပါသည်။

ပရိုဂရမ်အတွင်းတွင် အသုံးပြုမည့် အချက်အလက်များအား စုစည်း၍ လက်တွေ့ဘဝတွင် ရှိသော Object များအဖြင့် အစားထိုးပြီး၊ ထို Object များအား အပြန်အလှန် ခိုင်းစေခြင်းအားဖြင့် ရေးသားလိုသည့် လော့ဂျစ်အား အကောင်အထည်ဖော်စေသော Object Oriented ပရိုဂရမ်မင်း၏ အတွေးအခေါ်သည် ထိုခေတ်ထိုအခါနှင့် လွန်စွာကိုက်ညီသော နည်းပညာရပ်တစ်ခု ဖြစ်လာပါသည်။ အဘယ်ကြောင့်ဆိုသော် Class တစ်ခုအား တစ်ကြိမ်ရေးသားပြီး၊ ထို Class ၏ instance အား Object အဖြစ် နေရာတိုင်းတွင် အသုံးပြုနိုင်ခြင်းသည်၊ ရေးသားထားသော ကုဒ်များကို ပြန်လည်အသုံးချနိုင်ခြင်း ပင်ဖြစ်သောကြောင့် ဖြစ်ပါသည်။

ဤနည်းအားဖြင့် ၁၉၉၀ခုနှစ် ပိုင်းလောက်ကစ၍ လူသုံးစများလာသော Object Oriented ၏ အတွေးအခေါ်များသည်၊ ယနေ့ခေတ် အချိန်အခါ အရောက်တွင် C++, Java မှအစ Javascript၊ Python နှင့် PHP များအထိ အသုံးများသော ပရိုဂရမ်မင်း ဘာသာရပ်များတွင် အခြေခံ အတွေးအခေါ်အဖြစ် ဝင်ရောက် နေရာယူ ထားသည်ကိုတွေ့ရပါမည်။

ဆက်လက်၍ Object Oriented ၏ အခြေခံ အတွေးအခေါ်တစ်ခုဖြစ်သော မျိုးရိုးဆက်ခံခြင်း၏ ကောင်းကွက်၊ ဆိုးကွက်နှင့် အသုံးပြုသင့်သည့်နေရာများကို လက်တွေ့ နမှုနာများ ရေးသားရင်း ဆက်လက်လေ့လာသွားပါမည်။



လုပ်ဆောင်ချက်နှင့် ပိုင်ဆိုင်မှု့များကို ပြန်လည် အသုံးပြုနိုင်ခြင်း

ဥပမာအားဖြင့် Rectangle ဟု အမည်ရသော Class တစ်ခုရှိသည်ဟု စဉ်းစားကြည့်ပါမည်။ Rectangle တွင် length, width အစရှိသည့် အချက်အလက်များကို ပိုင်ဆိုင်ပြီး၊ Area ကို တွက်ယူနိုင်သော getArea လုပ်ဆောင်ချက်ကို ပိုင်ဆိုင်ပါသည်။ ဧရိယာကို တွက်ယူရာတွင်လည်း ထောင့်မှန်စတုဂံ ဖြစ်သောကြောင့် width * length ဖြင့် တွက်ချက်နိုင်ပါသည်။


တဖန် ဤနေရာတွင် Parallelogram ကို အသုံးပြုရန်လိုအပ်လာပါသည်။ ထိုအခါမျိုးတွင် Parallelogram ၏ ဧရိယာသည်လည်း base * height ဖြစ်ပါသောကြောင့် Rectangle ၏ လုပ်ဆောင်ချက်ကို ဆက်လက်အသုံးပြုသွားရုံဖြစ်၏။ ထို့ကြောင့် ဤနေရာမျိုးတွင် Parallelogram အား Rectangle ၏ Sub Class အဖြစ်တည်ဆောက်သွားပါမည်။

ShapeTest.java
class Ractangle {
 private double width = 0;
 private double length = 0;
 
 public Ractangle(double width, double length) {
  this.width = width;
  this.length = length;
 }
 
 public double getArea() {
  return this.length * this.width;
 }
}

class Parallelogram extends Ractangle {

 public Parallelogram(double width, double length) {
  super(width, length);
 }
}

public class ShapeTest {
 public static void main(String[] args) {
  calArea(new Ractangle(20, 12));
  calArea(new Parallelogram(24, 16));
 }
 
 public static void calArea(Ractangle ract) {
  System.out.println(ract.getClass().getName() + " : " + ract.getArea());
 }
}


အထက်ပါ ကုဒ်များအား ကွန်ပိုင်းလုပ်၍ အလုပ်ခိုင်းကြည့်ပါက အောက်ပါအတိုင်း တွေ့မြင်ရမည် ဖြစ်ပါသည်။
Ractangle : 240
Parallelogram : 384


Override နှင့် Polymorphism

အထက်ပါ နမှုနာမျိုးတွင် တြိဂံကိုလည်း အသုံးပြုလိုသည့်အခါရှိပါမည်။ သို့ရာတွင် တြိဂံသည် အခြေနှင့် အမြင့်ကို အသုံးပြုပါသော်လည်း ဧရိယာတွက်ကိန်းမှာ ထောင့်မှန်စတုဂံနှင့် မတူညီပါ။


ထိုအခါမျိုးတွင် Triangle သည် Rectangle ကို Extends လုပ်မည်ဖြစ်သော်လည်း getArea ကို မှု Rectangle ၏ getArea ကို မဟုတ်ပဲ မိမိကိုယ်ပိုင် getArea ကို အသုံးပြုရန်လိုအပ် လာပါသည်။ ထို့ကြောင့် getArea အမည်ဖြင့်လုပ်ဆောင်ချက်ကို ထပ်မံရေးသားပါသည်။ Java တွင် Super Class နှင့် Sub Class တွင် အမည်တူ လုပ်ဆောင်ချက်ကို ရေးသားထားပါက၊ Sub Class ကိုသာ အသုံးပြုမည် ဖြစ်သည်။

Super Class တွင်ရေးသားထားသော လုပ်ဆောင်ချက် တစ်ခုအား၊ Sub Class ဘက်တွင် ထပ်မံ ရေးသားချင်းကို Override ဟု ခေါ်ပါသည်။ ဤကဲ့သို့ တစ်ခုတည်းသော Class မှ ဆင်းသက်လာပြီး၊ ပုံစံအမျိုးမျိုး ပြောင်းလည်းနိုင်ခြင်းကို Polymorphism ဟုခေါ်ပါသည်။

ShapeTest.java
class Ractangle {
 private double width = 0;
 private double length = 0;
 
 public Ractangle(double width, double length) {
  this.width = width;
  this.length = length;
 }
 
 public double getArea() {
  return this.length * this.width;
 }
}

class Parallelogram extends Ractangle {

 public Parallelogram(double width, double length) {
  super(width, length);
 }
}

class Triangle extends Ractangle {

 public Triangle(double width, double length) {
  super(width, length);
 }
 
 @Override
 public double getArea() {
  return super.getArea()/2;
 }
}

public class ShapeTest {
 public static void main(String[] args) {
  calArea(new Ractangle(20, 12));
  calArea(new Parallelogram(24, 16));
  calArea(new Triangle(24, 16));
 }
 
 public static void calArea(Ractangle ract) {
  System.out.println(ract.getClass().getName() + " : " + ract.getArea());
 }
}


အထက်ပါ ကုဒ်များအား ကွန်ပိုင်းလုပ်ပြီး၊ အလုပ်လုပ်ခိုင်းကြည့်ပါက အောက်ပါအတိုင်း ဖော်ပြနိုင်ပါသည်။ ဖော်ပြပါအတိုင်း Triangle ကိုလည်း တွက်ချက်နိုင်သည်ကို တွေ့ရပါမည်။
Ractangle : 240.0
Parallelogram : 384.0
Triangle : 192.0


Abstract Class


တဖန် အထက်ပါ နမှုနာတွင် စက်ဝိုင်းကို ဖြည့်စွက်အသုံးပြုကြည့်ပါဦးမည်။ စဉ်းစားစရာ အချက်မှာ စက်ဝိုင်းသည် ထောင့်မှန်စတုဂံနှင့် ပိုင်ဆိုင်မှု့နှင့်ရော ဧရိယာ တွက်ချက်နည်းပါ မတူညီပေ။ ထို့ကြောင့် Rectangle အား Extends လုပ်၍ ရရှိသောအကျိုးမှာ ထင်သလုပ်ရှိမည် မဟုတ်။

သို့ရာတွင် ShapeTest ၏ static လုပ်ဆောင်ချက်ဖြစ်သော calArea ကို ပြန်လည်အသုံးပြုလိုပါသည်။ ShapeTest#calArea သည် ပါရာမီတာအဖြစ် Rectangle ၏ Object ကို ရယူပြီး၊ ထို Object ၏ getArea ကို ခေါ်ယူကာ ရရှိလာသော ရလဒ်အား ကွန်ဆိုးတွင် ရေးသား ဖော်ပြနေစေပါသည်။ တနည်းတွေးရမည် ဆိုလျှင် Rectangle နှင့် အမျိုးတူ Object ဖြစ်ရန် လိုအပ်ပြီး၊ getArea လုပ်ဆောင်ချက်ကို ပံ့ပိုးထားရန် လိုအပ်ပါသည်။

Java ဘာသာရပ်တွင် ဤအနေအထားမျိုး၌ Abstract Class ကို အသုံးပြု၍ ဖြေရှင်းနိုင်ပါသည်။ Abstract Class သည် လက်တွေ့ Object များကို ပြုလုပ်နိုင်ခြင်းမရှိသော ကလပ်စ် ဖြစ်ပြီး၊ ၎င်းအား အခြေခံသော Sub Class များကိုသာ ပြုလုပ်ခွင့်ရှိပါသည်။ Abstract Class တွင် Abstract လုပ်ဆောင်ချက်များကို ပိုင်ဆိုင်ခွင့်ရှိပါသည်။ Abstract လုပ်ဆောင်ချက်ဆိုသည်မှာ လုပ်ဆောင်ချက်၏ အမည်၊ ပါရာမီတာ နှင့် ရလဒ်ပုံစံများကို သာသတ်မှတ်ထားပြီး၊ လော့ဂျစ်များကိုမှု ရေးသားထားခြင်း မရှိပေ။ Sub Class မှ Abstract Class အား Extends လုပ်ရာတွင် အထက်ပါ Abstract လုပ်ဆောင်ချက်ကို Override လုပ်၍ လော့ဂျစ်များကို ရေးသားရပါမည်။

ဤနမှုနာတွင် Shape ဟုအမည်ရသော Abstract Class ကို ရေးသားပြီး၊ ၎င်းတွင် getArea ဟု အမည်ရသော Abstract လုပ်ဆောင်ချက်ကို ပိုင်ဆိုင်စေပါမည်။ တဖန် Rectangle နှင့် Circle ကို Shape အား Extends လုပ်စေပြီး၊ Rectangle နှင့် Circle ကို အမျိုးအစားတူ Object များအနေဖြင့် ShapeTest#calArea လုပ်ဆောင်ချက်တွင် အသုံးပြုစေမည် ဖြစ်ပါသည်။

ShapeTest.java
abstract class Shape {
 public abstract double getArea();
}

class Ractangle extends Shape{
 private double width = 0;
 private double length = 0;
 
 public Ractangle(double width, double length) {
  this.width = width;
  this.length = length;
 }
 
 @Override
 public double getArea() {
  return this.length * this.width;
 }
}

class Parallelogram extends Ractangle {

 public Parallelogram(double width, double length) {
  super(width, length);
 }
}

class Triangle extends Ractangle {

 public Triangle(double width, double length) {
  super(width, length);
 }
 
 @Override
 public double getArea() {
  return super.getArea()/2;
 }
}

class Circle extends Shape {
 
 private double radious;
 
 public Circle(double radious) {
  this.radious = radious;
 }

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

public class ShapeTest {
 public static void main(String[] args) {
  calArea(new Ractangle(20, 12));
  calArea(new Parallelogram(24, 16));
  calArea(new Triangle(24, 16));
  calArea(new Circle(24));
 }
 
 public static void calArea(Shape ract) {
  System.out.println(ract.getClass().getName() + " : " + ract.getArea());
 
}

အထက်ပါ နမှုနာထဲတွင် စာကြောင်း ၁ မှ ၃သည် Abstract Class Shape ဖြစ်ပြီး Abstract လုပ်ဆောင်ချက် getArea ကို ပိုင်ဆိုင်ပါသည်။ Rectangle နှင့် Circle တို့သည် အသီးသီး Shape အား Extends လုပ်ထားပြီး၊ ကိုယ်စီ getArea ကို override လုပ်နေကြပါသည်။ ဤနည်းအားဖြင့် Ractangle, Parallelogram, Triangle နှင့် Circle များသည် Shape အမျိုးအနွယ် ကလပ်စ်များဖြစ်ကြပြီး၊ အားလုံး ShapeTest#calArea လုပ်ဆောင်ချက်တွင် အသုံးပြုနိုင်ခြင်း ဖြစ်ပါသည်။
Ractangle : 240.0
Parallelogram : 384.0
Triangle : 192.0
Circle : 1809.5573684677208



သတိပြုရန် အချက်

မျိုးရိုးဆက်ခံမှု့နှင့် ပတ်သက်၍ နမှုနာများကိုပါ ရေးသားပြီး၊ လေ့လာခဲ့၏။ မျိုးရိုးဆက်ခံမှု့ဖြင့်၊ ရေးသားထားသော ကုဒ်များအား ပြန်လည်အသုံးပြုနိုင်ခြင်း၊ အုပ်စုတူ ကလပ်များကို သတ်မှတ်နိုင်ခြင်း အစရှိသည့် အကျိုးများကို ရရှိစေနိုင်ပါသည်။ သို့ရာတွင် မျိုးရိုးဆက်ခံမှု့ကြောင့် ကလပ်စ်တစ်ခုနှင့် တစ်ခု ပတ်သက် မှီခိုမှု့ကို ဖြစ်ပွားစေပြီး၊ ပြုပြင်ရခက်ခဲစေနိုင်ပါသည်။ ထို့ကြောင့် မျိုးရိုးဆက်ခံမှု့ကို အသုံးပြုရာတွင် ကုဒ်များအားပြန်လည် အသုံးပြုလိုခြင်း အကြောင်းတစ်ခုတည်းဖြင့် အသုံးမပြုသင့်ပေ။ အုပ်စုဖွဲ့အသုံးပြုလိုသည့်အခါများ၊ Framework များအား ရေးသားလိုသည့်အခါ များတွင် အသုံးပြုသင့်ပါသည်။

တဖန် Java ဘာသာရပ်တွင် Class တစ်ခုသည် တစ်ခုတည်းသော Super Class ကိုသာ Extends လုပ်နိုင်ပါသည်။ တစ်ခုသော Super Class အား Extends လုပ်ထားပါက အခြားသော ကလပ်စ်များအား ထပ်မံ၍ အမွေဆက်ခံနိုင်ခွင့် မရှိပေ။

No comments:

Post a Comment