[Day24] CH11:刘姥姥逛物件导向的世界——抽象、介面

今天要来介绍这个主题最後一个单元了,废话不多说就直接进入正题吧!

抽象(Abstract)类别与方法

在介绍「介面」前,要先介绍「抽象」这个概念。在现实生活中,有 Sheep、 Fish 等动物这个实体,但是却没有一种动物叫做 Animal,他就好像是一种概念,是抽象的,并不实际存在。

在定义类别时,可以只宣告方法名称而不实作(Implements),这样的方法称之为「抽象方法」(Abstract method),若类别中包括了抽象方法,则该类别称之为「抽象类别」(Abstract class),抽象类别是拥有未实作方法的类别,所以不能被用来生成物件,只能被继承扩充,并於继承後实作未完成的抽象方法,所以可以把抽象类别理解成他就是用来被继承的,如下所示:

public class Zoo3{
    public static void main(String[] args){
        Animal a = new Animal(); //error
    }
}

abstract class Animal{
    private String name;
    
    protected Animal(){

    } 
    
    protected Animal(String name){
        this.name = name;
    }

    public abstract String move(int units);

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name = name;
    }
}

class Sheep extends Animal{
    private String woolColor;

    public Sheep(){
        super();
    }

    public Sheep(String name, String woolColor){
        super(name);
        this.woolColor = woolColor;
    }

    public void setWoolColor(String woolColor){
        this.woolColor = woolColor;
    }

    public String getWoolColor(){
        return woolColor;
    }

    @Override
    public String move(int units){
        return "跑" + units + "步";
    }
}

执行後会出现以下错误:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    Cannot instantiate the type Animal

另外将 move() 改为抽象方法,只定义原形,再在 Sheep 去覆写,这样的写法又更简洁了,因此我们也可以把抽象方法理解为他就是用来被覆写的。

介面(Interface)

当无关的类别需要共用共通的方法及常数时,通常会使用介面。举例来说:我们前几天提到的 Animal 类别和植物(Plant)类别都具有生长(toGrow)这个方法,但 Animal 和 Plant 没有什麽关联,而且 Java 只能继承一个类别,所以 Sheep 继承了 Animal,就不能再继承 Grow 这个类别,这时就可以把 Grow 定义为介面,让 Sheep 和 Tree 都可以实作这个介面。

在介面中定义的栏位、方法都有规定好的修饰子,可以写也可以不写,但不能冲突。

public interface Grow{
    int height = 5;  //编译完会自行在执行档中加上 public static final
    void toGrow();    //编译完会自行在执行档加上 public abstract
}

实作时,必须实作所有该介面宣告的方法,否则会编译错误。要使用介面中的变数(height)的话,透过「介面名称.栏位名称」就可以呼叫。

public class Zoo4{
    public static void main(String[] args){
        Grow obj = new Sheep();
        obj.toGrow();
    }
}

class Sheep implements Grow{
    public void toGrow(){
        System.out.println("生长" + Grow.height + "公分");
    }
}
生长5公分

除此之外,Java 规定最多只能继承一个类别,但却可以实作多个介面,只要在 implements 後面用逗号分隔就可。特别的是,在介面中可以多重继承,如下所示:

interface 介面名称 extends 介面1, 介面2, ..., 介面n {

}

认识完介面,让我们来比较抽象类别和介面吧!

抽象类别 介面
用於被继承,子类别要实作定义的抽象方法。 用於被实作,子类别要实作定义的方法。
可以定义完整的方法,也可只定义方法原型。 只能定义方法原型。
定义完整的资料栏位供继承类别使用。 定义的资料栏位用於作为常数使用。

当没有预设的实作要继承时(没有栏位,也不需要预设的方法实作时),通常会使用介面来代替抽象类别。

物件导向的精华全部都在这四天所介绍的内容里了,当然物件导向还有非常多的概念,但我们就先理解这些就好了。今天已经是第 24 天了,感觉这一路走来非常的充实呢!剩下的几天,我们一起走完吧!/images/emoticon/emoticon12.gif


<<:  Day 10 : PHP - 常用的阵列函数有哪些?

>>:  予焦啦!Golang 记忆体初始化

资安学习路上-picoCTF 解题(General) 2

4. flag_shop 这题主要考C的整数溢位观念。 档案载下来发现是个c档案 打开後看一下程序码...

ASP.NET MVC 从入门到放弃 (Day6) -C#集合、IEnumerable ICollection IList介绍

接着来讲讲常用的集合写法.... Array(阵列): 是相同型别的集合 透过引索去取得元素 长度是...

awk-3 运算符与函数

前两篇回顾 awk - 简介 Linux 制表好工具 awk-2 Regex搭配浅谈 awk是个程序...

[Day 23] 让tinyML感受你的律动

话说为了要作出吃了会考试100分、会变聪明、变漂亮的「爆浆濑尿虾牛丸」,我特别找来庙街最重情义的火鸡...

Vue.js指令(v-model)绑定(DAY27)

现今常常会在购物网站中看到顾客点选产品时,网页会依据顾客的操作自动列出清单,或是看到一些使用者在输入...