概述
Java接口
前言
使用抽象类和抽象方法,可以控制基类不被实例化,同时控制派生类必须实现基类的抽象方法。
一个类中包含抽象方法,那么这个类就必须是抽象的;抽象类中的每一个抽象方法都必须要被派生类实现,抽象类中的抽象方法要加修饰符abstract;如果我们写一个抽象类,但从来都没有被实现过,那么这个抽象是垃圾代码。抽象类中是可以没有抽象方法的,一旦有抽象方法则规定子类必须要实现其抽象方法;
这里的接口是特指java中的interface;是比抽象类更进一步的抽象;interface接口的所有方法都必须是抽象的;接口中的所有方法默认都是public,且抽象的,所以不用加这两个修饰符;接口中定义的域是静态的,final的;实现接口用implements,表示当前这个类是这个接口的具体细节;implements接口后,实现的方法必须要加public,因为修饰符只能大不能小,不添加修饰符的话,就是默认包下访问权限,是比public小,要编译报错的。
1.完全解耦
当我们编写一个方法,方法接收一个具体类而非接口时,这个方法就只能接收这个类或其子类;如果我们想把方法给另外一个类使用,这个时候我们就要把方法接收的参数定义成接口;
虽然使用基类我们也可以实现多态,但是没有实现完全解耦。
使用基类的案例演示
package com.JavaSE04.demo02.interface_classprocesser;
import java.util.Arrays;
class Processor{
public String name(){
return getClass().getSimpleName();
}
Object process(Object input){return input;}
}
class Upcase extends Processor{
String process(Object input){return ((String)input).toUpperCase();}
}
class Downcase extends Processor{
String process(Object input){return ((String)input).toLowerCase();}
}
class Splitter extends Processor{
String process(Object input){return Arrays.toString(((String)input).split(" "));}
}
public class Apply {
public static void process(Processor p,Object s){//我们现在使用基类,这个方法我们现在只能给这个基类或其派生类去使用;不能给其他类使用
//没有做到完全解耦
System.out.println("Using Processor "+p.name());
System.out.println(p.process(s));
}
public static String s="Disagreement with beliefs is by definition incorrect";
public static void main(String[] args) {
process(new Upcase(),s);
process(new Downcase(),s);
process(new Splitter(),s);
}
}
根据上面实验代码,我们有了下面的改进方案:定义一个顶层接口,然后定义一个抽象类作基类,下面有具体类实现细节。
这是接口
package com.JavaSE04.demo02.interfaces.interfaceprocessor;
public interface Processor
{
String name();
Object proces(Object input);
}
这个抽象类继承了接口,并在这个编译单元中定义了很多个处理器class
package com.JavaSE04.demo02.interfaces.interfaceprocessor;
import java.util.Arrays;
//这个类的目的是把公共子类的部分,提出来。
public abstract class StringProcessor implements Processor{
public String name() {
return this.getClass().getSimpleName();
}
public abstract Object proces(Object input) ;
}
class Upcase extends StringProcessor{
public String proces(Object input) {//注:这里使用的协变返回类型
return ((String)input).toUpperCase();
}
}
class Downcase extends StringProcessor{
public String proces(Object input) {
return ((String)input).toLowerCase();
}
}
class Spliter extends StringProcessor{
public String proces(Object input) {
return Arrays.toString(((String)input).split(" "));
}
}
最后这是测试入口
package com.JavaSE04.demo02.interfaces.interfaceprocessor;
public class apply {
//这里使用的是接口,这样程序的可扩展性就高很多了。
//只要实现了这个接口的处理器,都可以传进来。
//这样我们的方法就不依赖于某一个具体的类
public static void process(Processor p,Object s){
System.out.println("Using Processor "+p.name());
System.out.println(p.proces(s));
}
public static String s="Disagreement with beliefs is by definition incorrect";
public static void main(String[] args) {
process(new Upcase(),s);
process(new Downcase(),s);
process(new Spliter(),s);
}
}
2.Java中的多重继承
java只能是继承一个类。但可以实现多个接口;Java中的多继承是指实现多个接口,我们可以把这个类称为每个接口下的具体实现类。
在java中extends只能继承一个类。但允许implements实现多个接口
实现多个接口时,必须用逗号隔开;实现接口时,必须把接口中个每一个抽象方法具体实现。
实现多个接口的目的,就是当我们要把new出来的对象向上转型时可以非常灵活。
以下是实验代码
package com.JavaSE04.demo03;
interface CanFight{
void fight();
}
interface CanSwim{
void swim();
}
interface CanFly{
void fly();
}
class ActionCharacter{
public void fight(){}//这个方法结构完全跟上面接口方法一样。所以下面实现了CanFight接口,而继承ActionCharacter中刚好有这个方法,不用再实现多一次,父类已经有了。
}
//在java中extends只能继承一个类。但允许实现多个接口
//实现多个接口时,必须用逗号隔开
class Hero extends ActionCharacter implements CanFight,CanFly,CanSwim{
public void swim() {
}
public void fly() {
}
}
public class adventure {
public static void t(CanFight x){ x.fight(); }
public static void u(CanSwim x){x.swim();}
public static void v(CanFly x){x.fly();}
public static void w(ActionCharacter x){x.fight();}
public static void main(String[] args) {
Hero hero = new Hero();//现在hero是全能的,什么都会
t(hero);
u(hero);
v(hero);
w(hero);
}
}
接口之间也可以继承,且可以继承多个接口,继承后子接口可以添加新的抽象方法。
以下是实验代码
package com.JavaSE04.demo03;
interface Monster{
void menace();
}
//额外新增一个接口的原因是:原来的接口已经正在使用,修改正在使用的接口,那么实现这个接口的类就要作出改变,这是很糟糕的。
//接口跟类的区别:子接口可以继承多个父接口,用逗号隔开
interface DangerousMonster extends Monster{
void destroy();
}
interface Lethal{
void kill();
}
interface Vampire extends DangerousMonster,Lethal{//实现了多个父接口(多重继承)
//扩展自己的方法
void drinkBlooad();
}
class VeryBadVampire implements Vampire{
public void menace() {
}
public void destroy() {
}
public void kill() {
}
public void drinkBlooad() {
}
}
//这个类实现了一个子接口,那么就要实现这个子接口本身及其父接口的方法
class DargonZilla implements DangerousMonster{
public void menace() {
}
public void destroy() {
}
}
public class HorrorShow {
static void u(Monster b){b.menace();}
static void v(DangerousMonster d){d.destroy();d.menace();}
static void w(Lethal l){l.kill();}
public static void main(String[] args) {
DangerousMonster barney = new DargonZilla();
u(barney);
v(barney);
Vampire edward = new VeryBadVampire();
w(edward);
}
}
当接口跟接口组合进行扩展时,可能出现接口名字重复的情况;若出现名称冲突会出现一些相应的信息,会导致程序无法正常运行。
当我们想要去组合或继承,要小心名字冲突,目前没有好的解决方案,除非重新设计名字。
以下是实验代码
package com.JavaSE04.demo03;
interface I1{void f();}
interface I2{int f(int i);}
interface I3{int f();}
class C{
public int f(){
return 1;
}
}
class C2 implements I1,I2{
public void f(){
}
public int f(int i) {
return 1;
}
}
class C3 extends C implements I2{
public int f(int i) {
return 1;
}
}
class C4 extends C implements I3{//父类的方法结构刚好跟I3接口中的方法结构一样;可选择重写或不重写
public int f(){return 1;}
}
//class C5 extends C implements I1{//这里会出问题;父类的方法跟父接口的方法名称相同,但结构又不一样,就会报错,是不允许的;
// public void f(){ }//重写之后,又跟继承父类的方法冲突
//}
//interface I4 extends I1,I3{//这也是不允许的;名称相同,结构不同,是会出错的;
// //IDEA错误提示 ‘f()' in 'com.JavaSE04.demo03.I3' clashes with 'f()' in 'com.JavaSE04.demo03.I1'; methods have unrelated return types
//
//}
public class TestName {
}
最后
以上就是文静月饼为你收集整理的JavaSE基础06-接口Java接口的全部内容,希望文章能够帮你解决JavaSE基础06-接口Java接口所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复