【达内课程】面向对象之接口

需要知道的知识点

1、百度百科的定义:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。

Java中的接口可以被看作是只包含常量和抽象方法的抽象类 。

2、接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。它和类的区别是用interface来代替class关键字,用implements来代替extends关键字。

接口的定义格式:

interface 接口名称{
  全局常量 ;
  抽象方法 ;
}

3、在一个接口中,只能定义常量、抽象方法,JDK1.8后可以定义默认的实现方法

4、接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。

5、类只能继承1个类,但可以实现多个接口

class A extends B implements C,D,E{
}

6、接口之间继承,接口继承接口可以多继承

interface A extends B,C,D{
}

7、java8新增
(1)增加了 default 方法和 static 方法,这两种方法完全可以有方法体
(2)default 方法属于实例,static 方法属于类(接口)
(3)接口中的静态方法不会被继承,接口中的静态变量会被继承

举例1:Weapon接口 ,理解接口的使用

我们创建一个武器接口 Weapon
定义了武器类型有:冷兵器(TYPE_CODE)、热兵器(TYPE_HEAT)、核武器(TYPE_NUCLEAR)
定义了武器的方法有 :攻击(kill)、获取武器名称(getName)、获取武器类型(getType)

接着我们创建冷兵器倚天剑类 Sword类和热兵器 AK47 类 都实现 Weapon 接口。

Weapon
|--------------冷兵器:倚天剑
|--------------热兵器:AK47

创建Weapon接口

public interface Weapon {
    //接口中的属性默认为public static final,所以可省
    public static final int TYPE_COLD = 1;
    int TYPE_HEAT = 2;

    //必须是公共、抽象的,public abstract可以省略
    //接口中的方法会被隐式的指定为 public abstract
    //而且只能是 public abstract(公共、抽象的),所以可省
    public abstract void kill(TextView textView);
    String getName();
    int getType();
}

创建Sword类

public class Sword implements Weapon {
    @Override
    public void kill(TextView textView) {
        textView.append("舞出了一套太极剑法");
    }

    @Override
    public String getName() {
        return "倚天剑";
    }

    @Override
    public int getType() {
        return Weapon.TYPE_COLD;
    }
}

创建AK47类

public class AK47 implements Weapon {
    @Override
    public void kill(TextView textView) {
        textView.append("连续射出了100发子弹");
    }

    @Override
    public String getName() {
        return "AK47";
    }

    @Override
    public int getType() {
        return Weapon.TYPE_HEAT;
    }
}

xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_transformer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="doClick"
        android:text="变形金刚" />

    <Button
        android:id="@+id/btn_sword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="doClick"
        android:text="倚天剑" />

    <Button
        android:id="@+id/btn_ak47"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="doClick"
        android:text="AK47" />

    <Button
        android:id="@+id/btn_kill"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="doClick"
        android:text="进攻" />

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textColor="#222222"
        android:textSize="20sp" />
</LinearLayout>

为了方便使用武器,我们创建一个变形金刚类 Transformer ,只要把创建的武器实例放到它手里(setWeapon()方法),然后就可以进行攻击了(调用attack()方法)

创建Transformer类

public class Transformer {
    private Weapon w;

    public void setWeapon(Weapon w) {
        this.w = w;
    }

    public void attack(TextView textView) {
        if (w == null) {
            textView.setText("没有武器,用牙咬吗?");
            return;
        }

        String type = "";
        switch (w.getType()) {
            case Weapon.TYPE_COLD:
                type = "冷兵器";
                break;
            case Weapon.TYPE_HEAT:
                type = "热兵器";
                break;
        }

        textView.setText("使用" + type + w.getName());
        w.kill(textView);
    }
}

MainActivity

public class MainActivity extends AppCompatActivity {
    Button btnTransformer;
    Button btnSword;
    Button btnAK47;
    Button btnKill;

    TextView textView;
    Transformer transformer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnTransformer = findViewById(R.id.btn_transformer);
        btnSword = findViewById(R.id.btn_sword);
        btnAK47 = findViewById(R.id.btn_ak47);
        btnKill = findViewById(R.id.btn_kill);
        textView = findViewById(R.id.text);
    }

    public void doClick(View view) {
        switch (view.getId()) {
            case R.id.btn_transformer:
                createTransformer(textView);
                break;
            case R.id.btn_sword:
                createSword();
                break;
            case R.id.btn_ak47:
                createAK47();
                break;
            case R.id.btn_kill:
                kill();
                break;
        }
    }

    private void createTransformer(TextView textView) {
        transformer = new Transformer();
        textView.setText("已经创建变形金刚");
    }

    public void createSword() {
        Sword sword = new Sword();
        transformer.setWeapon(sword);
        textView.setText("接入倚天剑");
    }

    public void createAK47() {
        AK47 ak47 = new AK47();
        transformer.setWeapon(ak47);
        textView.setText("接入AK47");
    }

    public void kill() {
        transformer.attack(textView);
    }
}

运行程序:
在这里插入图片描述

举例2:Bird 类 。接口使用之一:解决多重继承问题

Java 语言本身是不支持类的多重继承(多重继承是指一个类从多个类继承而来,即一个类拥有多个超类)的,但一个类却可以实现多个接口。这样,我们可以将一些抽象方法定义在接口中,间接地达到多重继承的目的。

我们现在有接口 MyInterface1有 飞翔(fly)方法、接口 MyInterface2 有行走(walk)方法

人类能走路所以可以实现 MyInterface2 。而鸟类既能走路也能飞翔,所以要实现 MyInterface1 和 MyInterface2 两个接口。这样就解决“多重继承”的问题

MyInterface1.java

public interface MyInterface1 {
    void fly();
}

MyInterface2.java

public interface MyInterface2 {
    void walk();
}

Bird.java

public class Bird implements MyInterface1, MyInterface2 {
    private static final String TAG = "Bird";

    @Override
    public void fly() {
        Log.i(TAG, "I can fly");
    }

    @Override
    public void walk() {
        Log.i(TAG, "I can walk");
    }
}

举例3:Calculator 接口 。接口使用之二:定义一个规范(协议)

同一个接口可以有多个不同的实现类,但每一个实现类都必须重写接口中所有的抽象方法。即接口不考虑这些实现类各自采用什么方式实现这些功能,但它要求所有的实现类都必须有这些功能。

例如:
首先定义一个计算器的接口:ICalculator.java,所有实现该接口的类,都必须具有计算两个数相加、相减、相乘、相除的功能。

ICalculator

public interface ICalculator {
    /**
     * 计算器可以计算两个数的和
     */
    int add(int a, int b);

    /**
     * 计算器可以计算两个数的差
     */
    int sub(int a, int b);

    /**
     * 计算器可以计算两个数的积
     */
    long mul(int a, int b);

    /**
     * 计算器可以计算两个数的商
     */
    float div(int a, int b);
}

创建实现该接口的类 ACalculator.java

public class ACalculator implements ICalculator {
    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public int sub(int a, int b) {
        return a - b;
    }

    @Override
    public long mul(int a, int b) {
        return a * b;
    }

    @Override
    public float div(int a, int b) {
        return (float) a / (float) b;
    }
}

测试使用

在其他类中使用 ACalculator 进行两数之和的计算,其他类并不需要了解ACalculator 是通过什么方式计算的,只需要了解 ICalculator 接口中的相关方法定义即可

ICalculator calculator = new ACalculator();
int sum = calculator.add(12, 14);
System.out.println("sum = " + sum);

运行结果:
在这里插入图片描述

举例4:OnInfoFetchCallback 。接口使用之三:用于回调

我们知道,一般情况下主线程是不执行耗时任务的,如果遇到一些耗时任务(如网络请求,文件读写,数据库读写等等),我们会将其放入子线程中去执行,当执行完毕后,子线程再将执行结果返回给主线程。这个过程就是回调

首先定义一个回调接口 OnInfoFetchCallback.java

public interface OnInfoFetchCallback {
    /**
     * 获取信息成功
     */
    void onSuccess(String info);

    /**
     * 获取信息失败
     */
    void failure();
}

再定义一个用于获取信息的任务类,在这个类中我们执行一些耗时操作 InfoService.java

public class InfoService {
    private OnInfoFetchCallback callback;

    public InfoService(OnInfoFetchCallback callback) {
        this.callback = callback;
    }

    public void getInfo() {
        // 模拟一个耗时操作
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(3000);
                // 信息获取成功,传递结果
                callback.onSuccess("结果是:" + new Date());
            } catch (InterruptedException e) {
                // 信息获取失败
                callback.failure();
            }
        });
        thread.start();
    }
}

xml 中放一个按钮来获取信息

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_getInfo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="doClick"
        android:text="获取信息" />

</LinearLayout>

MainActivity
在 MainActivity 中调用 InfoService 中的 getInfo() 方法执行耗时操作

public class MainActivity extends AppCompatActivity implements OnInfoFetchCallback {
    private static final String TAG = "OnInfoFetchCallback";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void doClick(View view) {
        switch (view.getId()) {
            case R.id.btn_getInfo:
                fetchInfo();
                break;
        }
    }

    /**
     * 获取信息
     */
    public void fetchInfo() {
        InfoService service = new InfoService(this);
        service.getInfo();
    }

    @Override
    public void onSuccess(String info) {
        Log.i(TAG, info);
    }

    @Override
    public void failure() {
        Log.i(TAG, "获取信息失败");
    }
}

由于 MainActivity 已经实现了 OnInfoFetchCallback 接口,所以在实例化 InfoService 对象时,直接将 this 传入即可。当任务执行结束后,调用 MainActivity 中的 onSuccess(String info)failure() 方法将结果返回

运行结果:
在这里插入图片描述
MainActivity 也可以不用实现 OnInfoFetchCallback 接口,此时可以采用匿名内部类的写法:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "OnInfoFetchCallback";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void doClick(View view) {
        switch (view.getId()) {
            case R.id.btn_getInfo:
                fetchInfo();
                break;
        }
    }

    /**
     * 获取信息
     */
    public void fetchInfo() {
        InfoService service = new InfoService(new OnInfoFetchCallback() {
            @Override
            public void onSuccess(String info) {
                Log.i(TAG, info);
            }

            @Override
            public void failure() {
                Log.i(TAG, "获取信息失败");
            }
        });
        service.getInfo();
    }
}

参考
Java 接口
java之面向对象详解-接口

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值