Java类的向上转型,向下转型的学习

类的一些基本概念,想必大家都已经了解了。
我之前对向上转型和向下转型也是一知半解,看了一篇blog感觉写的很好,照章来写点自己的理解。
直接进入正题吧。
先上代码,我们一步步来分析。

import java.util.ArrayList;
import java.util.List;

public class Transition {

    public static void Declaration(Animal a){
        a.speak();

    }
    public static void main(String[] args) {
        /*Animal cat=new Cat();
        Animal dog=new Dog();
        Animal pig=new Pig();
       cat.speak();
       dog.speak();
       pig.speak();*/

      /*  Declaration(new Cat());//自动向上转型Animal cat=new Cat();
        Declaration(new Dog());//Animal dog=new Dog();
        Declaration(new Pig());//Animal pig=new Pig();*/


        PetShop petShop=new PetShop();
        petShop.add(new Cat());
        petShop.add(new Dog());
        petShop.add(new Pig());
        petShop.getItem(0).speak();
 
/*        petShop.getItem(0).cat_Do();*/这里会报错,是运行不出来的,因为返回时一个Animal对象,不能用子类的方法。

        Cat cat=(Cat)petShop.getItem(0);
        cat.cat_Do();
        Dog dog=(Dog)petShop.getItem(1);
        dog.dog_Do();
        Pig pig=(Pig)petShop.getItem(2);
        pig.pig_Do();
    }
}

interface Animal {
    void speak();
}
class Cat implements Animal {
    public void speak(){
        System.out.println("i am a cat");
    }
    void cat_Do(){
        System.out.println("eat fish");
    }
}
class Dog implements Animal{
    public void speak(){
        System.out.println("i am a dog");
    }
    void dog_Do(){
        System.out.println("eat bone");
    }
}

class Pig implements Animal{
    public void speak(){
        System.out.println("i am a pig");
    }
    void pig_Do(){
        System.out.println("be the food for human being");
    }
}
class PetShop{
    private List<Animal> animalList=new ArrayList<>();
    public void add(Animal animal){
        animalList.add(animal);
    }
    public Animal getItem(int position){
        return animalList.get(position);
    }

}
首先先创建一个Animal的接口
interface Animal {
    void speak();
}

每个继承了这个接口的类,都必须要重写speak()方法;当然,也可以直接写一个空接口,这边为了方便一点。

写三个动物,继承Animal接口,它们分别是Cat,Dog,Pig。因为它们都是动物嘛
class Cat implements Animal {
    public void speak(){
        System.out.println("i am a cat");
    }
    void cat_Do(){
        System.out.println("eat fish");
    }
}
class Dog implements Animal{
    public void speak(){
        System.out.println("i am a dog");
    }
    void dog_Do(){
        System.out.println("eat bone");
    }
}

class Pig implements Animal{
    public void speak(){
        System.out.println("i am a pig");
    }
    void pig_Do(){
        System.out.println("be the food for human being");
    }
}

每个动物都会speak(),Cat会喵喵喵,Dog会汪汪汪,Pig会…(混吃等死),它们y也都有自己的特点。
当你问Cat的时候,Cat说“i am a cat”
当你问Dog的时候,Dog说“i am a dog”
当你问Pig的时候,Pig说“i am a pig”
但它们又有各自的特点:
Cat吃鱼 eat fish (这是它的特点)
Dog吃骨头 eat bone(这是它的特点)
Pig 被人吃 be the food for human being(这是它的特点) 我英文不好,所以表述不太好
我们来看

       Animal cat=new Cat();//向上转型
       Animal dog=new Dog();
       Animal pig=new Pig();
       cat.speak();
       dog.speak();
       pig.speak();

这里将Animal对象指向一个它的子类对象,所以Animal的对象只能用Animal本有的被重写的方法
可Animal不是一个接口吗,为什么接口能被实例化呢?
接口本身是不可实例化的,但是可以通过实现这个接口的类来实例化。
那Animal不是接口吗,为什么能继承呢?
我是这么理解的,接口就是为了多继承,我暂时姑且认为它是一个特殊的类。(大家百度一下就知道了)原谅我粗俗的理解
来看结果
在这里插入图片描述
但如果这么写

        Animal cat=new Cat();
        Animal dog=new Dog();
        Animal pig=new Pig();
        
        cat.cat_Do();
        dog.dog_Do();
        pig.pig_Do();

来看结果
在这里插入图片描述
Animal对象无法使用实现类自己的方法。它只能用接口里本有的被重写的方法。
将子类对象赋给父类对象,就是向上转型。但父类不能用子类特有的方法。

向上转型说完了,来讲向下转型

Animal有很多,我就想我有那么多的动物,我就开一家宠物店吧,一定可以暴富的。。
新建一个 PetShop类

class PetShop{
    private List<Animal> animalList=new ArrayList<>();
    public void add(Animal animal){
        animalList.add(animal);
    }
    public Animal getItem(int position){
        return animalList.get(position);
    }

}
List<Animal> animalList=new ArrayList<>();

这是建立一个存放Animal类型的数组animalList
那问题来了为什么存放的类型是Animal呢?为什么不是Cat,Dog或者是Pig呢?
现在只有三种动物,写三个List勉强可以应付,但如果有一万种(10,000)动物呢,我们是不是要写一万个list呢?
我们来看代码

 public void add(Animal animal){
        animalList.add(animal);
    }

为animalList添加Animal对象,是向上转型

 PetShop petShop=new PetShop();
        petShop.add(new Cat()); // new Cat()等同于Animal cat=new Cat();
        petShop.add(new Dog());//new Dog()等同于Animal dog=new Dog();
        petShop.add(new Pig());//new Pig()等同于Animal pig=new Pig();

这时候我们已经往animalList数组里插入了三种动物了,
我们可以通过petShop.getItem(0或1或2).speak(),知道它们是谁。
但是我们却不能知道它们的特性。也就是不能用
petShop.getItem(0).cat_Do,
petShop.getItem(0).dog_Do
petShop.getItem(0).pig_Do
应为它指向的是Animal对象,是不能用子类特有的方法。
这时候我们就需要用到向下转型

        Cat cat=(Cat)petShop.getItem(0);
        cat.cat_Do();
        Dog dog=(Dog)petShop.getItem(1);
        dog.dog_Do();
        Pig pig=(Pig)petShop.getItem(2);
        pig.pig_Do();

使用类型强制转换。在强制转换之前可以用instance of来检测。
这是时候动物们,便可以使用它们特有的方法了,我们就知道它们具体可以做什么了。
Android 中的比如 ListView listview=(ListView)findbyViewId(R.id.)其实也是这个道理。

这里面还有一个Declaration方法,大家可以自己理解一下,是向上转型。

 public static void Declaration(Animal a){
        a.speak();

原谅鄙人,肤浅的见解,文字表述可能真的不是很好,将就着看一下咯。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值