IT铁人DAY 4-物件导向基本概念(3)

修饰符(Modifier)

  上一篇有讲到封装的特性,也就是把一个类别要运行操作所需用到的资讯都包在一起,其中这些资讯的存取权限设定就相对重要,透过修饰符就可以控制资讯能够给谁使用、谁不能用,这样就能提高系统的安全性与完整。(修饰符可以套在方法或是类别之前)

  常见修饰符分为以下几种:

  1. public-即公开,如字面上所示,存取权限是最大的,只要套上这个修饰符,所有人的可以去使用。
  2. private-这个修饰符是存取权限最小的,只有类别自己本身可以去使用,要把资料隐藏就会需要用到这个。
  3. protected-保护这个修饰符一旦套上的话,就只有父类别与子类别才能够去做存取的动作。
  4. 没有修饰符-都没有套上和修饰符的话,那就是在同一个 package 里的类别都可以去使用
class Employee {
    int ID;
    protected String name;
    private 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{
    private String position = "工程师"
}

public class Company {

    public static void main(String []args) {
        Engineer Jack = new Engineer(123, "Jack", 30);
                
        Jack.selfIntrodution();
        System.out.println(Jack.name);
        System.out.println(Jack.age);
        System.out.println(Jack.ID);
    }
}

  如上面的程序范例所示,我们宣告了Jack为工程师类别,呼叫了父类别的selfIntrodution()方法,修饰符为public,任何类别皆可存取,这行没有问题。再来存取父类别的属性(name),修饰符为protected,而它们的关系是父子类别,这行也没有问题。接着试着去存取父类别的属性(age),修饰符为private,这表示只有父类别自己本身才能存取的属性,子类别没有存取的权限,所以编译会有错误,Jack能存取的private属性只有自己的position。最後去存取父类别的属性(ID),没有特定的修饰符,表示所有在此package的类别皆可存取,这行也就没有问题。

抽象类别(Abstract Class)

  关於抽象类别有几个重点:

  1. 抽象类别没办法被宣告成物件(实例化)。
  2. 如果此类别有抽象方法的话,那这个类别必须为抽象类别。
  3. 抽象类别的子类别必须复写所有的抽象方法。
abstract 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;
    }

    abstract void selfIntrodution();
}

class Engineer extends Employee{
    
    public Engineer(int id, String name, int age) {
        super(id, name, age);
    }
    
    public void selfIntrodution() {
        System.out.println("我是一位工程师");
    }
}

class Accountant extends Employee{
    
    public Accountant(int id, String name, int age) {
        super(id, name, age);
    }
    
    public void selfIntrodution() {
        System.out.println("我是一位会计师");
    }
}

  

  我在员工类别前面加了「abstract」,这就代表这是一个抽象类别,而抽象类别可以拥有抽象方法(selfIntrodution()),它可以不用去定义它的实作方式,要在子类别去复写。

  

介面(Interface)

  认识了抽象类别後,一定要在认识一下介面(Interface),介面封装了一些特定的功能,只要有类别实作此介面,就可以使用介面所有的属性和方法,现在请看以下范例程序码:

interface habit {
    void interest();
}

abstract 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;
    }

    abstract void selfIntrodution();
}

class Engineer extends Employee implements habit{
    
    public Engineer(int id, String name, int age) {
        super(id, name, age);
    }
    
    public void selfIntrodution() {
        System.out.println("我是一位工程师");
    }
    
    public void interest() {
        System.out.println("我爱写程序");
    }
}

class Kid implements habit {
    
    public void interest() {
        System.out.println("我爱看电视");
    }
}

public class Program {

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

//    result:
//        我爱写程序
//        我爱看电视

  我们可以看到工程师类别除了继承了员工类别外,还实作了习惯介面,另外小孩类别也实作了习惯介面,两个类别分别定义了介面的方法(interest()),分别是「我爱写程序」与「我爱看电视」。

  看到这里也许会有个疑问:已经有了抽象类别封装好共同需要的属性与方法,为甚麽还需要再多个介面来封装呢?

  答案就是当我们有两个以上的具体类别,但它们却不属於同一类别,就像是程序范例一样,工程师属於员工的一种,所以它继承了员工的属性;而小孩却不属於任何类别,但却又与工程师拥有「习惯」,因此我们把习惯写成介面,并让他们两个可以实作。换句话说,当我们在设计程序的时候,若有发现不同的类别有重复的内容,那就可以把这些重复的内容封装到抽象类别中,然後再由这些类别(子类别)去继承抽象类别(父类别);而介面是发现不同父类别中的子类别之间,有重复的特徵,因此把这些特徵封装到介面里,再由这些子类别去实作。

  简单来说,此特徵是在不同类的物件发生,那就用介面实作;若在相似的类别发生,就用抽象类别去继承。

  有父类别的概念後,我们就可以不用再一直写相同的程序码在不同的类别上,而且修改父类别,子类别也会跟着修改,就不需要每一个类别都改过,维护程序就变得简单多了;了解了修饰符後,可以让类别封装得更加完整、更具安全性。

  物件导向的基本概念就介绍到这边,接下来会说明在学习 Design Pattern 前需要了解的一些知识,这样就可以在学习的时候更快了解 Pattern 的架构与应用方式。


除此之外,也欢迎大家走走逛逛关於我们团队夥伴的文章
lu23770127 - SASS 基础初学三十天
10u1 - 糟了!是世界奇观!
juck30808 - Python - 数位行销分析与 Youtube API 教学
SiQing47 - 前端?後端?你早晚都要全端的,何不从现在开始?


<<:  19.移转 Aras PLM大小事-表单团队权限

>>:  [Day4] 安装Django

【情蒐阶段】确认自己的目标、熟悉职缺市场

今天早上泡了杯 wushwush,打开我的 Leetcode, 啊又是一个觉得智力不足的 momen...

DAY06 探索性资料分析

一、当拿到资料後 1.问自己,想要这笔资料为你做什麽? 举例来说,今天你拿到一笔资料,老板要你去预测...

Day33 ATT&CK for ICS - Impair Process Control

Impair Process Control 攻击者尝试修改、关闭、损坏影响物理控制流程,影响设备生...

[Day 1]从零开始学习 JS 的连续-30 Days---宣告变数

学习 JS Day 1 JavaScript 变数 变数就好比是资料容器,而资料又可以分为不同种类(...

[Day 30] 第二年的铁人赛:完赛心得

很快的 30 天过去了,终於完赛了,也是第二次参加铁人赛,去年第一次参加时自己还没养成写文章的习惯,...