上一篇有讲到封装的特性,也就是把一个类别要运行操作所需用到的资讯都包在一起,其中这些资讯的存取权限设定就相对重要,透过修饰符就可以控制资讯能够给谁使用、谁不能用,这样就能提高系统的安全性与完整。(修饰符可以套在方法或是类别之前)
常见修饰符分为以下几种:
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 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 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 - 前端?後端?你早晚都要全端的,何不从现在开始?
今天早上泡了杯 wushwush,打开我的 Leetcode, 啊又是一个觉得智力不足的 momen...
一、当拿到资料後 1.问自己,想要这笔资料为你做什麽? 举例来说,今天你拿到一笔资料,老板要你去预测...
Impair Process Control 攻击者尝试修改、关闭、损坏影响物理控制流程,影响设备生...
学习 JS Day 1 JavaScript 变数 变数就好比是资料容器,而资料又可以分为不同种类(...
很快的 30 天过去了,终於完赛了,也是第二次参加铁人赛,去年第一次参加时自己还没养成写文章的习惯,...