欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

Java 接口理解,对接口的理解

来源: javaer 分享于  点击 48216 次 点评:157

Java 接口理解,对接口的理解


学习Spring有一段时间了,对java也有了一点了解,最不能理解的就是接口, 即使是写了接口并实现了它,依然无法理解它到底有什么用?看了其他几篇博客,总结了一下自己的理解。

在JAVA编程语言中是一个抽象类型,是抽象方法的集合。一个类通过继承接口的方式,从而来继承接口的抽象方法。

先从一个通俗的解释看起 (原文:C# 接口《通俗解释》)


如果你的工作是一个修水管的,一天客户找上你让你帮装水管,但是有个要求,就是客户喜欢管子是三角形的。

你立马买了三角形的水管回来,在墙上弄个三角形的口子,客户付了钱,你很开心今天有了收入,如下图,很好:

//A写的Dog类,里面有个likeFood方法 class Dog { public void likeFood() { Print("我是小狗,我喜欢吃肉"); } } //B写的Cat类,里面有个likeFood方法,如下: class Cat { public void likeFood() { Print("我是小猫,我喜欢吃鱼"); } }

你写的Zoo类如下:

//动物园类
class Zoo {

    public void show(Dog dog){
        dog.likeFood();
    }

    public void show(Cat cat){
        cat.likeFood();
    }

}

在输出的时候使用如下:

void Main() 
{
    Zoo zoo = new Zoo();
    zoo.show(new Dog()); //"我是小狗,我喜欢吃肉"
    zoo.show(new Cat()); //"我是小猫,我喜欢吃鱼"
}

这一切工作良好,但好景不长,公司又需要给动物园增加一个猴子,让C去写这个Monkey类,并能输出它喜欢的食物。


class Dog 
{

    public void likeFood()
    {
        Console.WriteLine("我是小狗,我喜欢吃肉");
    }
    
}
//B写的Cat类,里面有个likeFood方法,如下:
class Cat 
{

    public void likeFood()
    {
        Console.WriteLine("我是小猫,我喜欢吃鱼");
    }
    
}
//C写的Monkey类,里面有个likeFood方法,如下:
class Monkey 
{

    public void likeFood()
    {
        Console.WriteLine("我是猴子,我喜欢吃桃子");
    }
    
}

于是你的Zoo类就变成了这样,仅仅多了一个重载方法:

class Zoo 
{
    public void show(Dog dog)
    {
        dog.likeFood();
    }

    public void show(Cat cat)
    {
        cat.likeFood();
    }

    public void show(Monkey money)
    {
        money.likeFood();
    }
}

void Main() 
{

    Zoo zoo = new Zoo();
    zoo.show(new Dog()); //"我是小狗,我喜欢吃肉"
    zoo.show(new Cat()); //"我是小猫,我喜欢吃鱼"
    zoo.show(new Monkey()); //"我是猴子,我喜欢吃桃子"

}

虽然只是增加了一个类,但善于思考的你马上就会想到:“如果后面还有更多动物要输出它们喜欢的食物,我的Zoo类都要修改,这对我来说不是一件好事。”
仔细观察Zoo类,发现不变的是show方法,变化的是show方法是参数。因为每个动物都不一样,所以参数也就不一样。所以原来就需要重载多个方法。
如果有一个类,能接收所有动物,那不就解决了?没错,于是你想到了定义一个父类叫Animal,里面有个likeFood方法,让所有动物类去继承Animal。

class Zoo 
{

    public void show(Animal animal)
    {
        animal.likeFood();
    }

}

class Animal 
{

    public void likeFood()
    {
        Print("我是Animal类");
    }

}

你告诉原来的A和B两人,让它们写的动物类都去继承Animal,并且里面有个输出动物喜欢食物的方法。

class Dog : Animal 
{

    public void likeFood()
    {
        Print("我是小狗,我喜欢吃肉");
    }
    
}

class Cat : Animal 
{

    public void likeFood()
    {
        Print("我是小猫,我喜欢吃鱼");
    }
    
}

class Monkey : Animal 
{

    public void likeFood()
    {
        Print("我是猴子,我喜欢吃桃子");
    }
    
}

运行也一切良好,不管你以后还有什么类,只要让需要添加的动物类,继承Animal,并有个likeFood方法,那么你无需修改Zoo,只需要再main方法里传入动物类的实例就能正常工作。
你大赞你聪明绝顶,这样一来,你的Zoo根本不需要改变了。
有一天,公司新来一个人,暂时叫D吧,公司让D写个兔子类,你告诉D,你写的Rabbit类必须继承Animal,并且有一个它喜欢的食物的方法。

class Rabbit : Animal 
{

    public void favoriteFood()
    {
        Print("我是兔子,我喜欢吃萝卜");
    }
    
}

void Main() 
{

    Zoo zoo = new Zoo();
    zoo.show(new Dog()); //"我是小狗,我喜欢吃肉"
    zoo.show(new Cat()); //"我是小猫,我喜欢吃鱼"
    zoo.show(new Monkey()); //"我是猴子,我喜欢吃桃子"
    zoo.show(new Rabbit()); //"我是Animal类"

}

Raabit并没有输出预想的结果,你不得不花了点时间去排查原因,最后你发现这不是什么大问题,因为新来的D虽然写了Rabbit类,但是他并不知道你们之前约定的动物喜欢的食物命名为:likeFood()
D写的Rabbit类,里面的方法叫:favoriteFood()
虽然最后D修改他的Rabbit类的方法为likeFood(),但你还是对这个问题做了一番思考,为什么会导致这个问题?
那是因为没有一种约束,使得子类继承父类的时候必须实现父类的方法。有没有一个类,能让它的子类必须实现它定义的方法?有,那就是接口
于是你修改Animal为接口,代码如下:

interface Animal {

    public void likeFood();
    
}

总结

由上述的例子可以总结接口的几个用处:

这里还有一个问题:在我写代码时,都是先有方法,对象,再有类,然后才去抽象成接口,那么我的每一个类都需要抽象成接口吗?在开发过程中,每写一个方法都要去写它的接口的抽象方法,实现它的serviceTest以及调用它的controllerTest,最后才能真正放到程序中去用,即使是一个小小的功能都要做很多“无用功”,而且需求一旦变更,改起来不是更麻烦?

相关文章

    暂无相关文章
相关栏目:

用户点评