【练习代码】6.11 java学习记录:继承与多态(实例:媒体资料库的设计)

设计一个媒体资料库,能存入不同类别的媒体资料,例如CD与DVD,并且能完成添加与列表等操作,需要些什么?

最基础的想法

一个代表整体库的DataBase类,内部的属性包括CD和DVD的Arraylist,对应操作通过定义自己的方法来实现,部分代码如下:

public class Database {
    private ArrayList<CD> listCD = new ArrayList<CD>();
    private ArrayList<DVD> listDVD = new ArrayList<DVD>();

    public void add(CD cd) {
       listCD.add(cd);
    }

    public void add(DVD dvd) {
       listDVD.add(dvd);
    }

    public void list() {
        for (CD cd : listCD) {
           cd.print();
       }
       for (DVD dvd : listDVD) {
           dvd.print();
        }

    }
}

因为需要CD和DVD的Arraylist,于是创造CD类和DVD类,并设置两者的内部属性和打印出内容的方法,以DVD的代码为例:

public class DVD  {
    private String title;
    private String director;
    private int playingTime;
    private boolean gotIt;
    private String comment;

    public DVD(String title, String director, int playingTime, String comment) {
        
        this.title = title;
        this.director = director;
        this.playingTime = playingTime;
        this.comment = comment;
    }

    public void print() {
        System.out.println("DVD:" + ":" + director);

    }
}

第一次优化:继承的使用

不难想到,CD类与DVD类的构建是完全类似的,除了个别特有的数据,两个类之间的高度相似导致了代码复制现象,代码复制是代码质量不良的体现,不仅从观感上显得臃肿且赘余,更导致代码的可拓展性不佳:假设需要向媒体库中添加新的类型,难免导致大量的代码增改。

因此,我们需要合理利用继承关系,将这些类归为同一父类的子类,其中所有复用的代码都来自对于父类的继承,这样我们不仅避免了代码复制现象,在新增类型时便无需改动其他部分的代码,只需使它继承那个父类。

于是我们在这里设计一个Item类,它具有CD类与DVD类的共同的属性与方法,代码如下:

public class Item {
    private String title;
    private int playingTime;
    private boolean gotIt;
    private String comment;

    public Item() {

    }

    public Item(String title, int playingTime, boolean gotIt, String comment) {
        //super();
        this.title = title;
        this.playingTime = playingTime;
        this.gotIt = gotIt;
        this.comment = comment;
    }



    public void print() {
        System.out.println(title);
    }
}

而CD类与DVD类修改为继承自Item,只需初始化Item类中没有的属性,并且重写Item类的print方法,使其符合自身需要,这次以CD类为例,代码如下:

public class CD extends Item {
    //private String title;
    private String artist;
    private int numOfTracks;
//    private int playingTime;
//    private boolean gotIt;
//    private String comment;

    public CD(String title, String artist, int numOfTracks, int playingTime, String comment) {
//        this.title = title;
        super(title, playingTime, false, comment);
        this.artist = artist;
        this.numOfTracks = numOfTracks;
//        this.playingTime = playingTime;
//        this.comment = comment;
    }



    public void print() {
        System.out.print("CD:");
        super.print();
        System.out.print(":" + artist);
    }
}

        super

        可以发现在对CD类的修改中有一处细节,由于属性仅在父类中,且访问属性设置为private,虽然子类确实继承了该属性,但是无法之间使用,因此需要利用super()访问,其使用方法及特性与关键字this类似,super指向当前对象的父类型特征,super()是当前对象构造方法中去调用自己父类的构造方法。

添加新媒体类型

完成继承关系的构造后,可以通过添加新的媒体类型来体会两者在方便程度上的显著区别——完全不需要改动DataBase中的代码,可以先看有了Item后、且Item的子类只有CD和DVD时DateBase的代码:

public class Database {
//    private ArrayList<CD> listCD = new ArrayList<CD>();
//    private ArrayList<DVD> listDVD = new ArrayList<DVD>();
    private ArrayList<Item> listItem = new ArrayList<Item>();
//    public void add(CD cd) {
//        listCD.add(cd);
//    }
//
//    public void add(DVD dvd) {
//        listDVD.add(dvd);
//    }

    private void add(Item item){
        listItem.add(item);
    }
    public void list() {
//        for (CD cd : listCD) {
//            cd.print();
//        }
//        for (DVD dvd : listDVD) {
//            dvd.print();
//        }
        for (Item item:listItem){
            item.print();
        }
    }
   public static void main(String[] args) {
        Database db = new Database();
        db.add(new CD("abc", "ai", 1, 20, "..."));
        db.add(new CD("c", "ai", 3, 20, "..."));
        db.add(new DVD("a", "i", 1, "..."));
        db.add(new DVD("X", "ai", 20, "..."));
        

        db.list();
    }
}

不难发现其中完全没有CD与DVD本身的出现,都是借助父类的特点——子类的对象可以赋值给父类的变量,实现与原本一致的效果;因此需要新增媒体类型时,只需完成对应类的构建,并在main函数中执行想要的操作就行,新增媒体类型VideoGame代码如下:

public class VideoGame extends Item {

    private int numberOfPlayers;

    public VideoGame(String title, int playingTime, boolean gotIt, String comment,int number) {
        super(title, playingTime, gotIt, comment);
        numberOfPlayers = number;
    }

    @Override
    public void print() {
        System.out.print("VideoGame:");
        super.print();
    }
}

        @Override

        对于@Override,这是一个告诉编译器的,下方所写是在覆盖父类的对应方法的标志。

        值得注意的是,通过父类的变量调用存在覆盖关系的函数时,会调用变量当时所管理的对象的所属类的函数。

运行效果

符合预期:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值