继承

@spiritree  August 15, 2016

以继承方式实现的媒体资料库,在课程代码实现的基础上,请实现一个表达MP3的媒体类型,能和CD、DVD一样存放进这个Database。

  • Item

public class Item {
    protected String title;
    protected int playingTime;
    protected boolean gotIt = false;
    protected String comment;


    public  Item(){

    }

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

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

public class CD extends Item {
    private String artist;
    private int numofTracks;
    private int playingTime;
    private boolean gotIt = false;
    private String comment;

    public CD(String title, String artist, int numofTracks, int playingTime, String comment) {
        super(title, playingTime, false, comment);  //如果有super就按照super的构造器.没有则寻找父类的构造器
//        this.title = title;
        this.artist = artist;
        this.numofTracks = numofTracks;
//        this.playingTime = playingTime;
//        this.comment = comment;
    }

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        CD cd = (CD) o;

        if (numofTracks != cd.numofTracks) return false;
        if (playingTime != cd.playingTime) return false;
        if (gotIt != cd.gotIt) return false;
        if (!artist.equals(cd.artist)) return false;
        return comment != null ? comment.equals(cd.comment) : cd.comment == null;

    }

    @Override
    public int hashCode() {
        int result = artist.hashCode();
        result = 31 * result + numofTracks;
        result = 31 * result + playingTime;
        result = 31 * result + (gotIt ? 1 : 0);
        result = 31 * result + (comment != null ? comment.hashCode() : 0);
        return result;
    }

    public static void main(String[] args) {
        CD cd1 = new CD("a", "a", 2, 60, "good");
        CD cd2 = new CD("a", "a", 2, 60, "good");
        System.out.println(cd1.equals(cd2));    //判断相等需要override新方法
    }
}

结果为:true

  • DVD

public class DVD extends Item {
    private String title;
    private String director;
    private int playingTime;
    private boolean gotIt = false;
    private String comment;

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

    public void print() {
        System.out.println("DVD:");
        super.print();
        System.out.println(director);
    }
}
  • Database

/**
 * 父类的东西都继承给了子类,如果父类有private则子类不能碰,但可通过父类的函数去碰
 * 在谁的函数里头指的那个成员函数变量就是谁的.如果子类父类出现同名的成员变量.
 * 子类父类都各自拥有.
 */
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(Item item)  //多态变量=不止一种类型的对象,它们可保存声明类型的变量,当把子类的对象赋给父类的对象时,就发生了向上造型.
    {
        listItem.add(item);
    }
//    public void add(CD cd) {
//        listCD.add(cd);

    public void list() {
        for (Item item : listItem ) {
            item.print();
        }
    }
//        for (CD cd : listCD) {
//            cd.print();
//        }
//    }
    public static void main(String[] args) {
        //不可能让一个对象赋值一个对象
        Database db = new Database();
        db.add(new CD("abc", "abc", 100, 60, "ok"));    //子类的对象可以传递给需要的父类对象的函数
        db.add(new CD("ddd", "abc", 100, 60, "ok"));
        db.add(new DVD("eee", "qqf", 120, "well"));
        db.list();
    }
}
  • 变量item可以引用任何item子类类型的对象(CD/DVD),这叫多态,即一种类型的变量,可引用多种实际类型对象。这样,对于变量item,它就有两个类型,类型item,我们称之为item的静态类型,类型CD/DVD,我们称之为item的动态类型。在Database的add方法中,db.add()调用的是其对应动态类型的add方法,这称之为方法的动态绑定

  • 子类对象赋值给父类引用变量,这叫向上转型,转型就是转换类型,向上转型就是转换为父类类型。

  • 使用继承一方面可以复用代码,公共的属性和行为可以放到父类中,而子类只需要关注子类特有的就可以了,另一方面,不同子类的对象可以更为方便的被统一处理。

  • new的过程中,父类的构造方法也会执行,且会优先于子类先执行。

  • super用于指代父类,可用于调用父类构造方法,访问父类方法和变量。

  • super的使用与this有点像,但superthis是不同的,this引用一个对象,是实实在在存在的,可以作为函数参数,可以作为返回值,但super只是一个关键字,不能作为参数和返回值,它只是用于告诉编译器访问父类的相关变量和方法。


添加新评论