iT邦幫忙

2021 iThome 鐵人賽

DAY 3
0
Software Development

淺談物件導向與Design Pattern介紹系列 第 3

IT鐵人DAY 3-物件導向基本概念(2)

  已經知道了類別與物件的差別以後,接下來就談談類別的方法該怎麼使用,以及物件導向的三大特性吧!


基本概念

方法(Method)

  簡單來說,方法內定義了一個類別可以做的事情,有呼叫才會去執行,沒呼叫則不會動作。我再舉昨天的程式範例做說明:

class Employee {
    int ID;
    String name;
    int age;
    int depID;
    String depName;

    public Employee(int id, String name, int age) {    //此為建構子(Constructor)
        ID = id;
        this.name = name;
        this.age = age;
    }

    //以下為方法(Method)
    public void setDepartment(int depID, String depName) {
        this.depID = depID;
        this.depName = depName;
    }

    public String getEmployeeInfo() {
        return "員工編號:" + ID + " 員工姓名:" + name + " 員工年齡:" + age;
    }

    public String getDepartment() {
        return "部門編號:" + depID + " 部門名稱:" + depName;
    }
}

public class Company {

    public static void main(String []args){

        Employee Jack = new Employee(123, "Jack", 45);
        Jack.setDepartment(12, "資訊部");
        System.out.println(Jack.getEmployeeInfo());

    }
}

//    result:
//        員工編號:123 員工姓名:Jack 員工年齡:45

  如上面的程式範例所示,我們宣告了Jack為員工類別以後,並呼叫了Jack的setDepartment()方法設定了depID與depName,然後再呼叫Jack的getEmployeeInfo()方法得到了Jack的基本資料把它印出來。

物件導向之三大特性

封裝 (Encapsulation)

  其實封裝已經在之前的範例呈現過了,不知道各位有沒有看出來?以之前的例子來說,封裝就是把一個類別所需要的資訊都包在一起,因此物件被創建以後,就不需要其他物件的幫忙,因為它本身已經擁有了運行操作所需要的資料。

  而封裝這個特性帶給了物件導向的程式減少耦合(Coupling),讓程式內的物件不互相影響,那這塊就比較偏系統分析了,就不多做說明,有興趣的人可以去搜尋「耦合和內聚」。

  

繼承(Inheritance)

  繼承這項特性會使類別間有了父子關係,子類別可以使用父類別中的屬性及方法,不過也不是全部都可以使用,端看於程式撰寫時賦予的修飾符而定,有關修飾符的知識後面會講解,現在請看以下範例程式碼:

class Employee {
    protected int ID;
    protected String name;
    protected int age;

    public Employee(int id, String name, int age) {
        ID = id;
        this.name = name;
        this.age = age;
    }

    public String getEmployeeInfo() {
        return "員工編號:" + ID + " 員工姓名:" + name + " 員工年齡:" + age;
    }
}

class Engineer extends Employee {
	
    public Engineer(int id, String name, int age) {
        super(id, name, age);
    }

    public void job() {
        System.out.println("我的工作是寫程式");
    }
}

public class Company {

    public static void main(String []args){
        Engineer Jack = new Engineer(123, "Jack", 30);

        System.out.println(Jack.getEmployeeInfo());
        Jack.job();
    }
}

//    result:
//        員工編號:123 員工姓名:Jack 員工年齡:30
//        我的工作是寫程式

  我一樣舉員工這個類別做範例,但不一樣的地方在於多了一個工程師類別,且繼承了員工類別的屬性與方法,所以我們宣告了Jack 是一個工程師,而工程師能夠用 Employee內的getEmployeeInfo()方法,還有個特別的地方是 Engineer 的建構子內有一個 super(),而這個 super() 會去找 Engineer 的父類別(Employee),賦予其該有的屬性,是不是很神奇呢!

  有了繼承這個特性,就可以創造不同的類別,而這些類別之間又有相同的屬性及方法,不需要重複寫那些相同的功能;不過繼承也是有它的缺點的,可以想到,既然子類別擁有父類別的方法,所以父類別只要修改,就會影響到子類別的實例,如果繼承的子類別很多,整個程式的耦合就會很高,影響的範圍就會很大。

多型(Polymorphism)

  多型這個特性是能夠改寫類別本身的方法,並且讓兩種以上的方法有相同的名稱,但是所帶的參數是不同的。那多型其實包含了多載(Overloading)和複寫(Overriding)。

  那甚麼是多載(Overloading)呢?其實就是在相同的類別內,有兩的相同名稱的方法,但它們所需要的參數不一樣,可能是參數個數不同,或是參數的型態不同,那只要利用方法之間所需要的參數差異,程式就可以呼叫到對應的方法,我們看以下程式範例:

class Employee {
    protected int ID;
    protected String name;
    protected int age;

    public Employee(int id, String name, int age) {
        ID = id;
        this.name = name;
        this.age = age;
    }
    //第一個方法
    public void job() {
        System.out.println("我的工作內容是寫程式!");
    }
    //第二個方法
    public void job(String position) {
        System.out.println("我的職稱是:" + position);
    }
}

public class Company {

    public static void main(String []args){
        Employee Jack = new Employee(123, "Jack", 30);

        Jack.job();
        Jack.job("工程師");
    }
}

//    result:
//        我的工作內容是寫程式!
//        我的職稱是工程師

  

  可以看到員工類別裡面有兩個同名的方法(job()),不過一個是不需帶參數,一個是要帶一個字串型態的參數,所以我們第一次呼叫沒有帶參數,程式對應到的是第一個方法,輸出的結果就是「我的工作內容是寫程式!」,而第二次我們帶了一個「工程師」的字串,程式自動對到第二個方法去執行,輸出結果為「我的職稱是工程師」。

  再來講甚麼是複寫(Overriding),與多載的差異其實就只是複寫他是發生在不同的類別,而這兩個類別有繼承關係,我們看以下程式範例:

class Employee {
    protected int ID;
    protected String name;
    protected int age;

    public Employee(int id, String name, int age) {
        ID = id;
        this.name = name;
        this.age = age;
    }

    public void selfIntrodution() {
        System.out.println("我的名子叫" + name + ",今年" + age + "歲!");
    }
}

class Engineer extends Employee {

    public Engineer(int id, String name, int age) {
        super(id, name, age);
    }

    public void selfIntrodution(String content) {
        System.out.println("我是一位" + content);
    }
}

public class Company {

    public static void main(String []args) {
        Engineer Jack = new Engineer(123, "Jack", 30);
                
        Jack.selfIntrodution();
        Jack.selfIntrodution("工程師");
    }
}

//    result:
//        我的名子叫Jack,今年30歲!
//        我是一位工程師

  

  程式中可以看到工程師類別子己也寫了一個與父類別方法同名的方法(selfIntrodution()),那第一次呼叫的方法沒有帶參數,所以程式對應到的是父類別(Employee)的方法,輸出的結果就是「我的名子叫Jack,今年30歲!」,而第二次我們帶了一個「工程師」的字串,程式自動對到子類別(Engineer)本身的方法去執行,輸出結果為「我是一位工程師」。

  相信看到這裡,有些人對於這些特性已經很了解了,而有些人還是百思不得其解。沒關係!因為我也沒有看一次就學會的天賦,在大學時期第一次聽完這些內容我也懵懵懂懂,不過還是要對自己所選的課程負責,反覆複習個幾遍,這些特性就會刻在腦海裡了。物件導向基本概念篇還沒結束,我們下一篇見!


除此之外,也歡迎大家走走逛逛關於我們團隊夥伴的文章
lu23770127 - SASS 基礎初學三十天
10u1 - 糟了!是世界奇觀!
juck30808 - Python - 數位行銷分析與 Youtube API 教學
SiQing47 - 前端?後端?你早晚都要全端的,何不從現在開始?


上一篇
IT鐵人DAY 2-物件導向基本概念(1)
下一篇
IT鐵人DAY 4-物件導向基本概念(3)
系列文
淺談物件導向與Design Pattern介紹30

尚未有邦友留言

立即登入留言