Бие даалтын ажлын  загвар: CS203 Объект Хандлагат Програмчлал                          2010-2011 оны хичээлийн жил                  

ЗАГВАР ЖИШЭЭ : “Завь түрээслэх, завь байрлуулах үйлчилгээ эрхэлдэг

Bradshaw Marina компанийн үйл ажиллагаа”

Өгөгдсөн загвар жишээнд хэрэгжсэн ойлголтууд:

Хэлэлцэх асуудал:

Анхаар!

Онолын ойлголт:

Java хэлэнд дахин тодорхойлогдсон аргын дараах 2 хэлбэр байдаг

Method override: Удамшлын харьцаан дахь эх классын аргатай ижил дүрслэлтэй аргыг хүү классд тодорхойлохыг хэлнэ. Өх: Тэдгээр аргуудын дүрслэл нь ижил харин гүйцэтгэх үүрэг нь өөр өөр байна.

Одоо өөрийн загвар системийн хувьд Method override хэмээх ойлголтыг хэрхэн хэрэгжүүлэх талаар авч үзье. Бидний өмнө тодорхойлсон Завь (Boat) класс нь байгуулагч арга ба гишүүд рүүгээ унших (getter) болон бичихээр (setter) хандах ерөнхий зориулалтын аргуудаас гадна өөрийн гишүүн өгөгдлүүдийнхээ утгыг буцаах tellAboutSelf() аргаар хангагдсан гэж үзье.

Boat

stateRegistrationNo;

lenght;

manufacturer;

year;

Boat()

    Getter functions &

    Setter functions

tellAboutSelf()

Хэдийгээр Завь (Boat) классаас удамших Моторт завь (PowerBoat) классд эх классынх нь tellAboutSelf() арга удамших боловч түүнд энэхүү аргыг дахин тодорхойлж өгөх боломжтой. Ингэснээр завь классын гишүүн өгөгдлүүдийг хэвлээд зогсохгүй хүү классын онцлог гишүүн өгөгдлүүдийг ч хэвлэх боломжтой болж байна.

PowerBoat

noEngines;

fuelType;

PowerBoat()

    Getter functions &

    Setter functions

tellAboutSelf()

Main() аргаас tellAboutSelf() аргыг дуудахдаа эх классын объектод бэхэлж дуудвал эх классын tellAboutSelf() арга дуудагдах бөгөөд харин хүү классын объектод бэхэлж дуудвал хүү классд дахин тодорхойлогдсон tellAboutSelf() арга дуудагдана. Үүнийг дараах жишээ програм тодорхой харуулна.

Энд Завь (Boat) классын програмын бичлэгийг үзүүлсэн байна. Түүнээс удамшсан Моторт завь (PowerBoat) классын програмын бичлэгийг авч үзье.

Энд Моторт завь (PowerBoat) классын tellAboutSelf() арга нь эх классынхаа гишүүдийн утгаас гадна өөрийн онцлог гишүүд болох noEngines болон fuelType гишүүдийн утгыг буцааж байна. Одоо дахин тодорхойлогдсон tellAboutSelf()  аргыг үндсэн аргаас хэрхэн дуудаж ажиллуулахыг авч үзье.

Програмын үр дүн:

Дээрх үр дүнгээс харахад

              firstBoat.tellAboutSelf()    гэж дуудахад эх классын арга дуудагдана.

              secondBoat.tellAboutSelf()    гэж дуудахад хүү классын дахин тодорхойлогдсон арга дуудагдана. Үүнтэй адилаар Завь(Boat) классаас удамших Сэлүүрт завь (SailBoat) классын хувьд мөн адил tellAboutSelf() аргыг дахин тодорхойлж ашиглаж болно.


Түрээс(Lease) нь 2 хэлбэрийн түрээс байж болно. Үүнд:

Тэгэхээр Түрээс классаас дээрх 2 түрээс удамшина. Тэдгээр хүү классуудад Түрээс классын

хүү класс нь өөрийн онцлог гишүүдээр хангагдсан байна.

Түрээс (Lease) классын програмын бичлэгийг хамтдаа авч үзье.

import java.util.*;

abstract class Lease {

        private double amount;

        private Date startDate;

        private Date endDate;

        

        public double getAmount() {

                return amount;

        }

        public void setAmount(double amount) {

                this.amount = amount;

        }

        public Date getEndDate() {

                return endDate;

        }

        public void setEndDate(Date endDate) {

                this.endDate = endDate;

        }

        public Date getStartDate() {

                return startDate;

        }

        public void setStartDate(Date startDate) {

                this.startDate = startDate;

        }

        public Lease(Date startDate) {

                setStartDate(startDate);

                setEndDate(null);

                setAmount(0);

                }

        

        public abstract double calculateFee(int aLenght);

}

Энд     public abstract double calculateFee(int aLenght); гэсэн мөрөнд түрээсийн төлбөр бодор сalculateFee() аргыг abstract -аар зарлаж өгсөн нь Түрээс (Lease) классаас удамших классууд энэхүү хийсвэр аргын хэрэгжилтийг агуулах ёстой. Өөрөөр хэлбэл: Хүү классуудад тухайн аргыг override хийх шаардлагатай гэсэн санаа.

Одоо Жилийн түрээс(AnnualLease), Хоногийн түрээс (DailyLease) гэсэн хүү классуудын програмын бичлэгийг авч үзье.

import java.util.*;

class AnnualLease extends Lease{

        private double balanceDue;

        private boolean payMounthly;

        

        public double getBalanceDue() {

                return balanceDue;

        }

        public void setBalanceDue(double balanceDue) {

                this.balanceDue = balanceDue;

        }

        public boolean isPayMounthly() {

                return payMounthly;

        }

        public void setPayMounthly(boolean payMounthly) {

                this.payMounthly = payMounthly;

        }

public AnnualLease(Date aStartDate, int aSlipWidth, boolean aPayMounthly)

        {

                super(aStartDate);

                Calendar aCalendar=Calendar.getInstance();

                aCalendar.setTime(aStartDate);

                aCalendar.add(Calendar.YEAR,1);

                setEndDate(aCalendar.getTime());

                setAmount(calculateFee(aSlipWidth));

                setPayMounthly(aPayMounthly);

                if(payMounthly)

            {setBalanceDue(getAmount()-getAmount()/12);}

                else setBalanceDue(0);

                }

        

        public double calculateFee(int aWidth){

                double fee;

                switch(aWidth ){

          case 10: fee=800;

                break;

                

                case 12: fee=900;

                break;

                

                case 14: fee=1100;

                break;

                

                case 16: fee=1500;

                break;

                

                default: fee=0;

          }

                return fee;

        }

}

Энд эх классын calculateFee(int aLenght); аргыг override хийх замаар жилийн түрээсийн хэмжээг тооцоолж байна.

Харин одоо хоногийн түрээс классын хувьд програмын бичлэгий авч үзье.

import java.util.*;

class DailyLease extends Lease{

        private int numberOfDays;

        public int getNumberOfDays() {

                return numberOfDays;

        }

        public void setNumberOfDays(int numberOfDays) {

                this.numberOfDays = numberOfDays;

        }

    public DailyLease(Date aStartDate, Date aEndDate, int aSlipWidth) {

        super(aStartDate);

        Calendar aCalendar=Calendar.getInstance();

        aCalendar.setTime(aStartDate);

        int day1=aCalendar.get(Calendar.DAY_OF_YEAR);

        aCalendar.setTime(aEndDate);

                 

        int day2=aCalendar.get(Calendar.DAY_OF_YEAR);

        setNumberOfDays(day2-day1);

        setEndDate(aEndDate);

        setAmount(calculateFee(aSlipWidth));

                 

        }

        public double calculateFee(int aWidth){

                double fee;

        switch(aWidth ){

                case 10: fee=20*getNumberOfDays();

                break;

                

                case 12: fee=25*getNumberOfDays();

                break;

                

                case 14: fee=30*getNumberOfDays();

                break;

                

                case 16: fee=35*getNumberOfDays();

                break;

                

                default: fee=0;

          }

                return fee;

        }

}

Энд мөн эх классын calculateFee(int aLenght); аргыг override хийх замаар хоногийн түрээсийн хэмжээг тооцоолж байна.

Эндээс харахад эх классын аргыг хийсвэрээр тодорхойлж өгсөнөөр тэрхүү хийсвэр аргын хэрэгжилтийг түүний хүү класс бүр агуулах шаардлагатай болохыг харуулж байна.

Одоо хамтдаа дээрх классуудыг хэрэглэх жишээ програмыг авч үзье.

import java.util.Calendar;

import java.util.Date;

public class TesterFinal {

        public static void main(String args[]){

                Calendar aCalendar=Calendar.getInstance();

                

                aCalendar.set(2003, Calendar.AUGUST,28);

                Date date1=aCalendar.getTime();

                

                aCalendar.set(2003, Calendar.SEPTEMBER,3);

                Date date2=aCalendar.getTime();

                

                aCalendar.set(2003, Calendar.SEPTEMBER,7);

                Date date3=aCalendar.getTime();

                

    AnnualLease firstLease= new AnnualLease(date1,14,true);

    AnnualLease secondLease= new AnnualLease(date2,16,false);

                

          DailyLease thirdLease= new DailyLease(date1, date2, 14);

          DailyLease fourthLease= new DailyLease(date2, date3, 16);                

                

          System.out.println("AnnualLease 1 information is:"

                                + firstLease.getAmount()+" "

                                + firstLease.getStartDate()+" "

                                + firstLease.getEndDate()+" "

                                + firstLease.getBalanceDue()+" "

                                + firstLease.isPayMounthly()+" "

                                );

                        

         System.out.println("AnnualLease 2 information is:"

                                + secondLease.getAmount()+" "

                                + secondLease.getStartDate()+" "

                                + secondLease.getEndDate()+" "

                                + secondLease.getBalanceDue()+" "

                                + secondLease.isPayMounthly()+" "

                                );

         System.out.println("DailyLease 1 information is:"

                                + thirdLease.getAmount()+" "

                                + thirdLease.getStartDate()+" "

                                + thirdLease.getEndDate()+" "

                                + thirdLease.getNumberOfDays()+" "

                                );

         System.out.println("DailyLease 2 information is:"

                        + fourthLease.getAmount()+" "

                        + fourthLease.getStartDate()+" "

                        + fourthLease.getEndDate()+" "

                        + fourthLease.getNumberOfDays()+" "

                                );

        }

}

Дээрх програмын үр дүн:

             

AnnualLease 1 information is: 1100.0 Thu Aug 28 22:14:38 ULAST 2003 Sat Aug 28 22:14:38 ULAST 2004 1008.3333333333334 true

AnnualLease 2 information is: 1500.0 Wed Sep 03 22:14:38 ULAST 2003 Fri Sep 03 22:14:38 ULAST 2004 0.0 false

DailyLease 1 information is: 180.0 Thu Aug 28 22:14:38 ULAST 2003 Wed Sep 03 22:14:38 ULAST 2003 6

DailyLease 2 information is: 140.0 Wed Sep 03 22:14:38 ULAST 2003 Sun Sep 07 22:14:38 ULAST 2003 4


Java хэлэнд дахин тодорхойлогдсон аргын дараах 2 хэлбэр байдаг

Method overloading гэдэг нь классд ижил нэртэй хэд хэдэн аргыг тодорхойлж ашиглах боломжийг олгодог. Тэдгээр аргууд нь нэрээрээ адилхан харин параметрээрээ ялгагдана.

class Slip {  private int slipID;

         private int width;

         private double slipLenght;

         private static int numberOfSlips=0;

         private static final int DEFAULT_WIDTH=12;

         private static final int DEFAULT_LENGHT=25;

         public Slip(int anID, int aWidth, double aSlipLenght){

        setSlipID(anID);        

        setSlipWidth(aWidth);        

        setSlipLenght(aSlipLenght);

        numberOfSlips++;

        }

          /*******Overloading cunstructors*********************/

 public Slip(int anID){this(anID, DEFAULT_WIDTH, DEFAULT_LENGHT);}

                public void setSlipID(int anID){ slipID=anID;        }

                public void setSlipWidth(int aWidth){        width=aWidth; }

public void setSlipLenght(double  aSlipLenght)

                                     { slipLenght=aSlipLenght; }

                public static int getNumberOfSlips()

                                                                                  {return numberOfSlips;}

                public int getSlipID(){        return slipID;        }

                public int getWidth(){        return width;        }

                public double getSlipLenght(){  return slipLenght;}

 

                 public String tellAboutSelf(){

                    String info;           

                    info="Slip Id="

                            +getSlipID()+", Width="

                            +getWidth()+", lenght="

                            +getSlipLenght();

                    return info;

            }

                 public double leaseSlip(){   double fee;

                  switch(width){

                  case 10: fee=800;          break;

                  case 12: fee=900;          break;                  

                  case 14: fee=1100;  break;                  

                  case 16: fee=1500;  break;                  

                  default: fee=0;                  }

                  return fee;          }

         

    /*******Overloading custom methods******************/

                         

            public double leaseSlip(double aDiscountPercent){

                             double fee=this.leaseSlip();

                             double discountedFee=fee*(100-aDiscountPercent)/100;

         return discountedFee;

           }

      }

Дээрх Зогсоол (Slip) классын хувьд  DEFAULT_WIDTH ба DEFAULT_LENGHT гэсэн final , static хувьсагчийг зарласан байна.


Классуудын шаталсан харьцааны 2 хэлбэр байдаг. Удамшил ба бүрдмэл.

Манай жишээнд “Хэрэглэгч завьтай” гэсэн өгүүлбэрзүйн хобоос үүсч байна. Тэгэхээр эдгээр классуудын хооронд шаталсан харьцаа үүсч байна гэж ойлгож болно. Энэ харьцааг програмын бичлэгт хэрхэн хэрэгжүүлэхийг авч үзье.

                 class Boat {

                private String stateRegistrationNo;

                private double lenght;

                private String manufacturer;

                private int year;

        

public Boat(String aStateRegistrationNo, double aLenght, String aManufacturer, int aYear )

                {        setStateRegistrationNo(aStateRegistrationNo);

                        setLenght(aLenght);

                        setManufacturer(aManufacturer);

                        setYear(aYear);

                }

               

        public void setLenght(double lenght)

                {        this.lenght = lenght;        }

        public void setManufacturer(String manufacturer)

                {        this.manufacturer = manufacturer;        }

public void setStateRegistrationNo(String stateRegistrationNo)

                    {        this.stateRegistrationNo = stateRegistrationNo;                }

        public void setYear(int year)

                {        this.year = year;        }

        public double getLenght()

                {        return lenght;        }

        public String getManufacturer()

                {        return manufacturer;        }

        public String getStateRegistrationNo()

                {return stateRegistrationNo;        }

        public int getYear()

                {        return year;        }

        }

Энд завь (Boat) классын бичлэгийг тодорхойлсон байна. Одоо Үйлчлүүлэгч (Customer) классыг аьч үзье.

class Customer {

        private String name;

        private String address;

        private String phoneNo;

        

private Boat boat;  // Энэ мөрийг анхаар!!!

        

public Customer(String aName, String anAddress, String aPhoneNo ){

                setName(aName);

                setAddress(anAddress);

                setPhoneNo(aPhoneNo);

                setBoat(null);

        }

        public String getAddress() {

                return address;

        }

        public void setAddress(String address) {

                this.address = address;

        }

        public Boat getBoat() {

                return boat;

        }

        public void setBoat(Boat boat) {

                this.boat = boat;

        }

        public String getName() {

                return name;

        }

        public void setName(String name) {

                this.name = name;

        }

        public String getPhoneNo() {

                return phoneNo;

        }

        public void setPhoneNo(String phoneNo) {

                this.phoneNo = phoneNo;

        }                

}

Эндээс харахад Үйлчлүүлэгч (Customer) классын

Өөрөөр хэлбэл: энэ нь класс хоорондын шаталсан харьцааны нэг жишээ юм. Манай жишээний хувьд Үйлчлүүлэгч ба Завь классуудын хоорондын шаталсан харьцаа үүсч байгаа бөгөөд энд Завь класс нь бүрэлдэхүүн класс харин Үйлчлүүлэгч класс нь бүрдмэл буюу үндсэн класс болно.

Одоо дээрх классуудыг хэрэгжүүлэх жишээ програмыг авч үзье.

public class TesterAssociation {

        public static void main(String args[]){

                Customer firstCustomer= new Customer("Eleanor","Atlanta","123-4567");

                Boat firstBoat=new Boat("MO34561",28,"Ttartsan",2002);

                firstCustomer.setBoat(firstBoat);

                

                Boat aBoat= firstCustomer.getBoat();

                System.out.println("Boat Information is: "

                                +aBoat.getStateRegistrationNo()+" "

                                +aBoat.getManufacturer()+" "

                                +aBoat.getLenght()+" "

                                +aBoat.getYear());

                System.out.println("Again, Boat Information is: "

                        +firstCustomer.getBoat().getStateRegistrationNo()+" "

                                +firstCustomer.getBoat().getManufacturer()+" "

                                +firstCustomer.getBoat().getLenght()+" "

                                +firstCustomer.getBoat().getYear());

}

}

Дээрх жишээ програмын

                System.out.println("Boat Information is: "

                                +aBoat.getStateRegistrationNo()+" "

                                +aBoat.getManufacturer()+" "

                                +aBoat.getLenght()+" "

                                +aBoat.getYear());              гэсэн мөрүүдэд

Завь классын объектод бэхлэн аргуудыг дуудах замаар тухайн объектын гишүүдийн утгыг хэвлэж байна. Харин

                System.out.println("Again, Boat Information is: "

                                +firstCustomer.getBoat().getStateRegistrationNo()+" "

                                +firstCustomer.getBoat().getManufacturer()+" "

                                +firstCustomer.getBoat().getLenght()+" "

                                +firstCustomer.getBoat().getYear());   гэсэн мөрүүдэд Бүрдмэл классын объект нь түүний бүрэлдэхүүн классын аргуудыг дуудаж ашиглах боломжтой тул энд Үйлчлүүлэгч классын объектоор дамжуулан Завь классын аргуудыг дуудах замаар Завьны гишүүдийг хэвлэж байна.

Харин эсрэгээрээ бүрэлдэхүүн классаас бүрдмэл (үндсэн) классын гишүүд рүү хандах боломжтой юу? Энэ асуултын хариуг дээрх кодонд жижигхэн өөрчлөлт хийх замаар бие даан туршиж үзээрэй.

10

Бэлтгэсэн: Д.Энхжаргал