最近,我这个菜鸟、初级、头发还较多年轻的程序猿接触到了抽象(听起来就让人头大)与接口这两个让人头昏脑壳涨的知识点。我真的很开心呢。。。
对于抽象,大家先听听它的描述吧!是什么呢?就是当一个方法呀,WE,我们只能确定它的实现部分,或者它的实现部分要交给子类去实现的时候呢,就是在这种情况下,我们就不应该直接给它打上“ { } ”了,而是直接申明部分书写“ ; ”来结束。
语法上呢,抽象方法应该在修饰符中增加一个这个东西:abstract(抽象的)。就是这么简单粗暴!这是一个可选修饰符哦。写出来大概就是这个样子的:
public abstract class Person {
private String name;
public abstract void papapa();
}
解释一下下哈:就是呢,比如人这个类,都有一个共同属性,比如说name(名字)。这个没啥好说的,人呢,也都有啪啪啪(老司机应该都懂)这个行为。但是具体实现(自行脑补,哈哈!),每个人就不太一样咯!因为每个人可能拥有的这个行为具体的实现方式(姿势)就不太一样了。所以,我们不知道具体到每个对象的时候的实现方式。因此,我们就傲娇的选择了不写。但是呢,加了抽象的方法它必须得有一个人陪,不然多寂寞呀!因此呢,类class前也得加abstract。这样,才能够使编译给个pass,而不给红牌来报错。但是,因为方法是它很傲娇的,所以,如果你class要变成抽象的,那么,对不起,我方法想不加就不加,就是这么傲娇!所以可以看出,有抽象方法的类一定是一个抽象类,但是,抽象类呢,它就不一定有抽象方法,防止被new了出来。
还有就是抽象类它是不能来产生对象的,因为它的作用啊,就是来充当父类的(他就是来当爸爸的)也可以说它是个模板。意思就是说,**抽象类,它是提取了所有具有共同行为或者属性的类的根类。**就好像是很多男孩子都玩王者荣耀,但是每个人玩的英雄不一样,位置也不一样。但是,我们都是在玩王者荣耀这个游戏,都有这个行为,只是实现的方式不一样。**子类继承父类的行为并用abstract来强制进行方法的具体实现。是IS–A的关系。**就是这样色儿的!
public class Superman extends Person {
@Override
public void papapa() {
System.out.println("我能在空中那个啥。。");
}
}
而用abstract有个好处就是我们不用担心我们会漏掉或者忘记重写的方法,子类继承之后,会强制实现者重写该方法。另一个好处就是,保证了设计者的设计意图,会被传递下去。
为什么不提抽象属性呢?因为压根就没有。那构造方法呢,构造方法也是不行滴!因为构造方法都不能被继承,所以抽象构造方法显得毫无意义。
好啦,讲完了抽象,喝口水继续讲接口这个东东。讲接口之前,我们先来看看,为毛线,要有接口这个东西呢?这个机会其实是抽象给的,为啥,继承在Java中由于是单继承,所以造成了一些不可避免的缺陷,bug。其一,就是,没有继承关系的类,其实也可以有共同行为。怎么理解这句话呢?来,老夫,不对,小生开一波车。在上面提到人这个类,有一个行为叫啪啪啪(狗头略过。。。)。但是,仔细一想,那个动物好像也有这个行为吧!人跟动物。。。不对,动物之间啪啪啪难道不叫啪啪啪吗?人家也是有性生活的哦!其二,上面提到,这个单继承太死板了,造成了灵活度不高的问题,丰富度也不够。咱们本着Java的健壮性以及什么性,忘了。。。反正就是你这个继承根本说不过去!他喵的,那就再整一个呗!整就整!于是,砰地一声巨响,接口就这样诞生了!(那个,嗯~补充一下,面向对象的编程到后面就会过渡到面向接口的编程哦!)它的出生,解决了继承的缺陷,因为这个B!他可以多实现,多实现,多实现(重要的事情说三遍),你的,懂?就是比单继承高级,懂了吧!
先说语法吧,定义的语法是:
1、关键字interface
2、接口往往要写成name+able,比如你要写个Fly飞的行为接口,就是这样:Fliable(这就是传说中的来自于程序员之间的py交易,潜规则,不成文的规定)。大概意思就是你的接口名字具有什么样的能力,比如我写的Fliable,飞的能力。代码就是这样色儿的:
public interface Fliable {
public void fly();
}
3、公共接口的的名字,必须与它所在的java文件名是保持一致的,反正就是嫁鸡随鸡,嫁狗随狗。
4、接口的访问修饰符子只能是public,就算不写,也是默认的为public,而不再是同包(就是脸皮够厚)。
当然,人家也是有属性的,但是,这一窝子都是些死犟死犟的牛脾气,因为定义的属性只能是public static final。当然也可以是省略成默认的,不用说也知道,他也是公共静态常量。
还与其一脉相承的是抽象方法(都是抽象方法哦),访问修饰符只能是public,可以省略public abstract。反正默认为公共抽象的。反正就是一样一样儿的。
同继承类似滴,接口也不能有构造方法,也不能有初始化块,统统都不能有。管你是实例的,还是静态的。因为它只关注一个东西,那就是行为,或者叫实现。
接下来,我们来了gai了gai具体的实现呗!接口与类的实现叫啥呢,不叫搞对象,叫做实现(关键字implements),后面呢,跟上接口名。然后ni,这个类就被称为接口的实现类。这之中大概体现了一种LIKE–A的关系。
那么,咱们还得注意几点:
public class Bird implements Fliable{
@Override
public void fly() {
System.out.println("我用翅膀飞");
}
}
(不要在意细节,看看语法就好)
1、一个类可以在继承父类的同时又实现接口,语法上是先写继承,再写实现。如果没有继承,则默认继承Object(根类,所有类都继承于它,是个老祖宗,但不用供着)。
2、一个类呀,如果实现了接口,该接口中所有抽象方法都必须实现。否则这个类就是抽象类。怎么理解这句话呢,要我说就是,接口说,你这个实现类有本事就实现老子的所有抽象方法,没本事就别逼逼,不然你就跟大爷姓吧,姓抽象。(或者就是你**儿今天要是实现不完,你*儿就跟到我姓)(这个在抽象里面没有说到,抽象类也适用这个东东)。
3、类从接口中获取的方法继承给子类。这个时候就是普通的继承关系嘛,所以就可以继承给子类。继承是单继承,但是ni,接口可以多实现,可以多继承。
public class SmartPhone extends Phone implements Gameable, Internetable, Mesagable, Musicable, Videoable {
@Override
public void watchVideo() {
System.out.println("权力的游戏第八季正在播放");
}
@Override
public void listenMusic() {
System.out.println("周杰伦:还记得你说家是唯一的城堡,随着稻香河流继续奔跑~~~~~");
}
@Override
public void sendMesage() {
System.out.println("短信正在发送");
}
@Override
public void surferInternet() {
System.out.println("QQ登陆中。。。");
}
@Override
public void playGame() {
System.out.println("(王者)张黔伟的凯真垃圾");
}
@Override
public void call() {
System.out.println("美女,你在什么啊,好久没给你打电话了");
}
}
总而言之,接口暴露类的行为,隐藏类的实现细节。就是说,接口的引用指向实现类对象。而对于调用者来说,只需要获取到接口的引用即可。但通过这个接口,调用者知道他可以调用哪些行为。但是ni,他是不会知道具体的实现类如何实现这些行为的。
好了,就说到这里吧!再多讲,我也说不出来,部分内容纯属瞎扯,望广大猿友擦亮脑门。。不对,擦亮双眼。愿与广大猿友共同学习,进步。不喜勿喷。嘻嘻。。。