java基础学习(八)接口

一、抽象类和抽象方法
抽象类是介于普通类与接口之间的一种通用接口。

抽象类的目的是通过这个通用接口操作一系列的类,创建抽象类的实体对象几乎没有任何意义。抽象类可以阻止使用者实例化该类。

抽象方法:仅有声明而没有方法体。
包含抽象方法的类叫做抽象类。如果一个类包含一个或多个抽象方法,该类必须被限定为抽象的,否则,编译器就会报错。
这里写图片描述
正确的方式:

public abstract class Instrument {
    private int i;
    public String what(){
        return "Hello niceeee";
    }
    //抽象方法必须写在抽象类中
    public abstract void play(String str);
}

当抽象类是不完整的(也就是存在抽象方法),那么试图产生该类的对象时,编译器会报错。
这里写图片描述
如果从一个抽象类继承,并创建该导出类的对象,那么必须为基类中的所有抽象方法提供方法定义。

public abstract class Instrument {
    private int i;
    public String what(){
        return "Hello niceeee";
    }
    public abstract void play(String str);

}

class Wind extends Instrument{
  //导出类必须实现基类中的抽象方法
    public void play(String str){
        System.out.println("str = [" + str + "]");
    }
}

当然,导出类也可以不实现基类中的方法,但是此时导出类也是抽象类,编译器会强制使用abstract来限定该类。

public abstract class Instrument {
    private int i;
    public String what(){
        return "Hello niceeee";
    }
    public abstract void play(String str);

}

//导出类可以不实现基类的抽象方法,当时该导出类被限定为抽象类
    abstract class  Percussion extends Instrument{
       private  String s="good";
    }

也可以创建一个没有任何抽象方法的抽象类。但是不能直接实例化。
这里写图片描述

二、接口
interface关键字产生一个完全抽象的类,根本没有提供任何具体实现。它允许创建者确定方法名、参数列表和返回类型,但是没有任何方法体。只提供形式,而未提供任何具体实现。

接口可以包含域,这些域隐式地是static和final的。并且是public的

//添加public关键字,仅限于该接口与文件同名,被添加则是包访问权限
public interface Instrut {
    //域是static & final  ,必须要初始化
    int value=5;

    //没有任何方法实体
    public void play(String str);
    public void adjust();

}

接口中的方法应该显式的声明为public,即使没有声明为public,它们自动都是public。这样的方法在被继承(implements)的过程中,必须被指定为public的,否则只得到包访问权限,而编译器不允许其访问权限被降低。

public interface Instrut {
    //域是static & final  ,必须要初始化
    int value=5;

    //显式声明方法为public
    public void play(String str);
    //可以不声明为public,但是自动默认是public
    void adjust();

}

class Stringed implements Instrut{
    public void play(String s){
        System.out.println("s = [" + s + "]");
    }
    //实现接口中的方法时,对于接口中没有声明public的方法,必须显式声明为public。不能降低访问权限
    public void adjust(){

    }
}

三、完全解耦
1、策略设计模式
能够根据所传递的参数对象的不同而具有不同行为的方法。这类方法包含所要执行的算法中固定不变的部分。而”策略”包含变化的部分,也就是传递进去的参数对象。

public class Apply {

    //该方法操作类而不是接口,那么只能使用这个类及其子类
    //该部分固定不变,根据所传递参数对象的不同,而执行不同行为
    //Processor对象就是一个策略
    public static void process(Processor p,Object s){
        System.out.println("using Processor:  "+p.name());
        System.out.println(p.process(s));
    }
    public static String test="this is a test";

    public static void main(String[] args) {
        process(new Upcase(),test);
        process(new Downcase(),test);
    }
}

//是一个类,而不是接口
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();
    }
}
//结果:
using Processor:  Upcase
THIS IS A TEST
using Processor:  Downcase
this is a test

在上例中,必须要使用Processor类型作为参数,才能使用其方法。从而导致Apply.process()方法和Processor之间的耦合过紧。这对于功能相同(方法相同)但是只是方法名不一样的类来说,会出现重复代码。

但是如果Processor是一个接口,那只要实现(implements)该接口就可以调用其方法:

public abstract class StringProcessor implements ProcessorTest{
    public String name() {
        return getClass().getSimpleName();
    }
    public abstract String process(Object input);
    public static String str="this is a test also";
    public static void main(String[] args) {
        ApplyTest.process(new UpcaseTest(),str);
    }

}


//接口
interface ProcessorTest{
    String name();
    Object process(Object input);
}

class ApplyTest{
    //该方法操作接口ProcessorTest
    public static void process(ProcessorTest pt,Object s){
        System.out.println("Using Processor  "+pt.name());
        System.out.println(pt.process(s));
    }
}

class UpcaseTest extends StringProcessor{
    public String process(Object input) {
        return ((String)input).toUpperCase();
    }
}
结果:
Using Processor  UpcaseTest
THIS IS A TEST ALSO

在上例中,ProcessorTest接口变得更加通用了,只要具有相同的功能元素,都可以使用该接口,而不一定要使用继承类的形式。

四、java中的多继承
在导出类中,不强制要求必须有继承一个是抽象的(抽象类)或具体的(没有任何抽象方法的普通类)基类。
如果要从一个非接口的类继承,那么只能从一个类去继承,其余的基元素都必须是接口。具体类必须放在前面,后面跟着接口。

//可以继承具体基类,实现接口
public abstract class Hero extends CanFly implements CanFight{
}
//继承一个抽象类,实现一个接口
abstract class Action extends CanSwim implements CanFight{

}
//不强制要求必须继承一个抽象或具体的基类,可以直接实现一个接口
abstract class Adventure implements CanFight{}

//接口
interface CanFight{
    void fight();
}
//抽象类
 abstract class CanSwim{
    abstract void swim();
}

//具体类
class CanFly{
    public void fly(){

    }
}

使用接口的原因:
1、为了能够向上转型为多个基类型
2、防止客户端程序员创建该类的对象(与抽象基类相同)
应该使用接口还是抽象类?如果要创建不带任何方法定义和成员变量的基类,那么就应该选择接口而不是抽象类。如果知道某事物应该成为一个基类,那么应该使它成为一个接口。

五、通过继承扩展接口
通过继承,可以在接口中添加新的方法声明,还可以在新接口中组合数个接口:

public class DragonZilla implements DangerousMonster{
    public void destroy() {
    }

    public void menace() {
    }
}

interface Monster{
    void menace();
}

interface DangerousMonster extends Monster{
    void destroy();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值