Java接口与类的关系理解

1、接口不能实例化对象。

刚学Java会觉得莫名其妙,因为随处都可以看到类似下面的代码:

接口 obj = new 接口Impl();

以为这里是用接口实例化对象,其实是错的。这行代码实际做了两件事:声明和赋值。声明是说对象obj是一个接口类型的对象,赋值是说obj被赋予一个接口具体实现的对象。接口就像模具,它是一个空壳子,可能有各种不同材质的产品实现,但是你没办法把模具当成真正的产品来用。如果把接口类比成“生物”,你就可以这样:

生物 person = new 人();
生物 animal = new 动物();
生物 plant = new 植物();

你说person、animal以及plant都是生物,这是没问题。但是生物是一个模糊的概念,没有具体的实物与之对应,所以我们在赋值的时候,需要new具体的实现类,也就是人、动物或是植物。

2、接口为什么不能实例化对象?

这个问题在中文网站搜索根本找不到答案,因为几乎没有关心或者大家都心知肚明。之所以接口不能实例化一个对象,是因为接口根本没有具体的实现,它只规定了实现该接口的类有哪些行为,但这些行为如何做,没有说。拿上面的例子来说,我们都知道只要是生物都可以吸收营养,但是人、动物还有植物吸收营养的具体过程是各不相同的。如果我说这是一个生物(即声明对象:生物 unknow = new 生物()),当我要求它吸收营养时,它该怎么做呢?转化成代码如下:

public interface 生物{
    @Override
    public void 吸收营养();
}

可以看的出,处于接口生物下的吸收营养方法,没有具体的实现,只是一个方法声明。那么如下代码有什么用呢?

生物 unknown = new 生物();
unknow.吸收营养();    // 这里到底是怎么吸收营养的?这个生物该做什么?

即便发出了让生物吸收营养的指令,生物也准备吸收营养,但真的去吸收营养时,却发现不知道该做什么。这就是接口实例化对象的接口,一个没有任何实现的对象,无论你对它做什么操作,它都会感到手足无措。

3、接口有什么用?

接口的意义就如之前提到的模具一样它给各种实现类提供了一个规范,它告诉使用者实现该接口的类大概长成什么样子,可以做什么事,只是它不关心具体怎么做而已。与其说是接口,不如通俗说它是一个总称。就好像我说你给我画一个多边形,你画三角形、四边形、五边形、六边形......都是对的,多边形是总称(接口),N变形是具体实现。但如果你不自动脑补,你根本不知道多边形该怎么画,因为你不知道多边形到底有几条边。

还以生物为例,何为生物,人、动物、植物这些都是生物,当然还有其它生物,就好比还有一边形(圆),只有当我们需要时,我们才会去提出它。下面就是几个对生物接口的具体实现类:

class 人 implements 生物{
    @Override
    public void 吸收营养(){
        System.out.println("吃饭");
    }
}

class 动物 implements 生物{
    @Override
    public void 吸收营养(){
        System.out.println("吃食");
    }
}

class 植物 implements 生物{
    @Override
    public void 吸收营养(){
        System.out.println("光合作用");
    }
}

现在接口有用了,它可以让几个具体实现类产生某种关系:它们可以统称为生物。但这还有没体现出接口实用之处,因为我们还没有实现这些具体类。

假设你被要求养一种生物,但这个生物前期是不明确的,你不知道它是人,是动物,还是植物。但是你不必紧张,因为你知道,无论它具体是什么,只要是生物,它都有吸收营养的能力,那你就不怕养不活它。所以,你可能面临的是这样的情况:

public class 喂养者 extends 人{
    public 喂养者(){
        // 你是一个人,同样也是一个生物,你也可以吸收营养
        this.吸收营养();
    }
    
    /**
     * 喂养对象声明成接口类型,就可以接收任意实现该接口的类对象作为参数
     * 如果不这样,有可能你就需要三个方法:喂养人、喂养动物、喂养植物
     */
    public void 喂养(生物 baby){
        baby.吸收营养(); // 这里是调用接口的方法吗?不是,这个方法是实参对象的方法!
    }
}

看,喂养方法似乎在说:我不知道你将交给我一个什么样的生物,但我知道,喂养它,就是让它吸收营养。接下来你就可以喂养你接手的生物了:

public class 生物喂养室{
    public static void main(String[] args){
        // 你来当喂养者吧
        喂养者 you = new 喂养者();
        
        // 这里有一个小孩
        生物 baby = new 人();
        // 喂养它吧
        you.喂养(baby);
        
        // 又有一只小动物要让你来喂养了
        生物 cat = new 动物();
        // 再不喂养,它可就要饿坏了
        you.喂养(cat);
        
        // 还有一盆花,给你的小屋增添不少生机
        生物 flower = new 植物();
        // 但你不能让它死了
        you.喂养(flower);
        
        // 累了吗,犒劳一下自己吧
        you.喂养(you);
    }
}

上面这些代码,既是接口的用处用法,又是接口使用场景。我的理解是,接口站在了更高的高度,它制定了一套流程,告诉别人哪一步应该做什么事,但具体怎么做,它不管你。所以我们可以看到,在java.sql包下,大部分都是接口,而具体的实现类,只有到用户使用的时候才会确定,是oracle、mysql还是db2。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值