Java学习笔记007——接口的应用

1、接口的转换(向下)

子类对向和父类对象可以进行类型转化。接口也一样可以。

package com.test;

// 接口Animal
public interface Animal {
    void bark(); //等价于public abstract void bark();
    void move(); //等价于public abstract void move();
}



package com.test;

// 通过接口Animal实现的Dog类
public class Dog implements Animal{
    public void bark() {
        System.out.println("狗在叫.");
    }
    public void move() {
        System.out.println("狗在奔跑。");
    }
}


// 通过接口Animal实现的Cat类
public class Cat implements Animal{
    public void bark() {
        System.out.println("猫在喵。");
    }
    public void move() {
        System.out.println("猫在跳。");
    }
}

// 通过实现两个接口,包括Animal接口的类Bird
public class Bird implements Animal,Flyable{
    public void bark() {
        System.out.println("鸟在唱歌。");
    }
    public void move() {
        System.out.println("鸟在蹦蹦跳跳。");
    }
    public void fly() {
        System.out.println("鸟在飞翔。");
    }
}


//
public class Zoo {
    public static void main(String[] args) {
        Animal[] animals = {new Dog(),new Cat(),new Bird()};
        for (Animal an : animals) {
            an.bark();
            an.move();
        }
        ((Flyable)animals[2]).fly();
    }
}

上面代码有两个接口Animal和Flyable,类Dog、Cat分别实现了Animal接口,类Bird同时实现了Animal和Flyable两个接口。

因为类Dog、Cat、Bird都实现了接口Animal,上面代码中定义的Animal类型的数组animals中的成员可以包含Dog、Cat、Bird类的实例对象。即下面一行代码是被Java允许的:

Animal[] animals = {new Dog(),new Cat(),new Bird()};

这样,数组中animals的元素(Animal类型变量)可以执行Animal接口中定义的,并在Dog、Cat、Bird类中实现的方法(bark()和move())。

animals[2]是Bird类的实例对象,但是它被声明成父接口Animal类型,要使用Bird类中实现的Flyable接口中的fly()方法,需要“向下转换”,即使用一对括号(子类/子接口)把animals[2]转换为Flyable接口类型,然后就可以调用Flyable接口中定义的,在Bird类中实现的fly()方法,如下代码:

((Flyable)animals[2]).fly();

需要明白的是:经过(Flyable) 进行转化后的animals[2](Bird类的实例),仅有接口Flyable定义的Bird类中实现的fly()方法。

可以这样理解:

(1)Bird类实现了Animal接口和Flyable接口;

(2)变量animals 被声明成Animal接口类型,但是通过Bird类创建的实例对象animals[2],这个变量animals[2]就像是被封印了非Animal接口中定义的其它方法,仅能使用Animal接口中定义的在Bird类中实现的方法。

(3)通过Flyable接口进行强制转化通过Bird类创建的实例对象animals[2],就像是解封了Bird类中实现的Flyable接口中的方法(fly()方法),但是也同时封印了非Flyable接口中定义的其它方法(bark()和move()方法)。

2、接口的转换(向下)

package com.test;

public class Trainer {
    // 定义一个属性,类型是Animal接口
    private Animal animal;

    // 动物园里的驯兽师类Trainer构造方法
    public Trainer(Animal an) {
        this.animal = an;
    }

    // 驯兽师的进行驯兽方法
    public  void train() {
        animal.bark();
        animal.move();
    }
}
package com.test;

public class Zoo {
    public static void main(String[] args) {
        // 使用Animal接口类型声明animals数组
        // 数组animals的成员分别是实现了Animal接口的Dog、Cat、Bird类
        Animal[] animals = {new Dog(),new Cat(),new Bird()};

        // 创建动物园驯兽师类的实例对象
        Trainer trainer;
        for (Animal an : animals) {
            trainer = new Trainer(an);
            trainer.train();
        }
    }
}

前一部分的代码建立了类Dog、Cat、Bird都实现了Animal接口。

在驯兽师Trainer类中定义了Animal接口类型变量animal,通过构造函数Trainer(Animal an),传入的Animal接口类型变量animal,赋值给Trainer类中定义的私有变量animal(是Animal接口类型),在Tainer类的训练方法train()方法中执行Animal接口中定义的方法(bark()和move())。

在Zoo类中的main()函数中:

(1)定义了animals数组,数组类型是Animal,但是数组中的元素是都实现了Aniaml接口的Dog、Cat、Bird类的实例对象。这些对象都具有Animal接口中定义的方法(bark()和move())。

(2)创建驯兽师类Trainer的实例,传入给Trainer的实例的方法train()的实参是animals数组,其中的元素分别是Dog、Cat、Bird类的实例对象。根据传入的实参不同,执行不同的类的实例对象的方法(bark()和move())。

通过设计Trainer类,就不需要针对每个动物去创建对应的驯兽师类(DogTrainer、CatTrainer、BirdTrainer)了。

为了再增加其他动物,只要这个动物实现了Animal接口,就可以在Zoo类中创建相应的实例对象,加入到声明为Animal类型的数组animals中。Trainer类不用做任何修改,即可训练这个动物了,当然只能训练Animal接口中定义的、在该类中实现的动作(bark()和move())。

这样,未来仅需要修改Animal接口(丰富训练内容),及创建实现Animal接口的更多动物类,Trainer类和Zoo类中的代码不用做任何修改,动物园的动物们都可以得到驯兽师(Trainer类)的训练。

上面的阐述特别的啰嗦,只是这让我比较清晰地理解了上面代码的意义。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值