多媒体资料设计

第一版

import java.util.ArrayList;

public class Datebase {

    private ArrayList<CD> listCD = new ArrayList<CD>();//用提示直接创建CD类

    public void add(CD cd) {
        listCD.add(cd); // 这个add是ArrayList的类库方法
    }

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

    public static void main(String[] args) {
        Datebase db = new Datebase();
        db.add(new CD("abc", "abc", 4, "...")); // add是调用public void add(CD cd)方法
        db.add(new CD("def", "def", 4, "..."));
        db.list();
    }

}
public class CD {

    private String title;
    private String artist;
    private int numOfTracks;
    private boolean gotIt; // 默认值为false
    private String comment;

    public CD(String title, String artist, int numOfTracks, String comment) {
    //顶部工具栏>Sourse>Generate Constructor Using Files..构造函数
    //这里不需要gotIt所以不需要勾选gotIt
       // super();//此时可有可无,这是继承的时候用到的
        this.title = title;
        this.artist = artist;
        this.numOfTracks = numOfTracks;
        this.comment = comment;
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

    public void print() {
        System.out.println(title + ":" + artist);

    }

}

输出结果

abc:abc
def:def

第二版(加入DVD)

import java.util.ArrayList;

public class Datebase {

    private ArrayList<CD> listCD = new ArrayList<CD>();  
    private ArrayList<DVD> listDVD = new ArrayList<DVD>(); // 设置一个DVD

    public void add(CD cd) {
        listCD.add(cd); // 这个add是ArrayList的类库方法
    }

    public void add(DVD dvd) { // 和cd一样的功能,方法重载就好
        listDVD.add(dvd);
    }

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

    public static void main(String[] args) {
        Datebase db = new Datebase();
        db.add(new CD("abc", "abc", 4, "...", 60)); // add是调用public void add(CD cd)方法
        db.add(new CD("def", "def", 4, "...", 60));
        db.add(new DVD("xxx", "aaa", 60, "...", 60));
        db.list();
    }

}
public class CD {

    private String title;
    private String artist;
    private int numOfTracks;
    private boolean gotIt; // 默认值为false
    private String comment;
    private int palyingTime;

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

    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

    public void print() {
        System.out.println("CD : " + title + ":" + artist);

    }

}
public class DVD {

    private String title;
    private String director;
    private int numOfTracks;
    private boolean gotIt; // 默认值为false
    private String comment;
    private int playingTime;

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

    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

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

    }

}

结果

CD : abc:abc
CD : def:def
DVD : xxx :aaa

Datebase 和 CD 和 DVD 的结构关系

大致是DateBase管理CD和DVD,然后CD和DVD又各自管理着自己的东西

第二版发现CD和DVD两个类非常的相似,DateBase也有很多相同的调用方式,不同的是一个是CD一个是DVD。这样的代码不具扩展性,难维护,你要一个一个去改,各个地方都要改。

第三版(改进版)

思路:从两个类中提取共同的东西,可以管CD 和DVD,然后DateBase管公共那个就好了

import java.util.ArrayList;

public class Datebase {   //注释掉的是原来的,表示新改进的不再需要了

    // private ArrayList<CD> listCD = new ArrayList<CD>();
    // private ArrayList<DVD> listDVD = new ArrayList<DVD>(); // 设置一个DVD
    private ArrayList<Item> listItem = new ArrayList<Item>();

    // public void add(CD cd) {
    // listCD.add(cd); // 这个add是ArrayList的类库方法
    // }
    //
    // public void add(DVD dvd) { // 和cd一样的功能,方法重载就好
    // listDVD.add(dvd);
    // }

    public void add(Item item) { // 不再对DVD或者CD做操作,现在只对Item做操作
        listItem.add(item);
    }

    // public void list() {
    // for (CD cd : listCD) {
    // cd.print();
    // }
    // for (DVD dvd : listDVD) {
    // dvd.print();
    // }
    // }
    public void list() {
        for (Item item : listItem) {
            item.print();   //同样使用警告提示帮我们在Item做一个print();
        }
    }

    public static void main(String[] args) {
        Datebase db = new Datebase();
        db.add(new CD("abc", "abc", 4, "...", 60)); // add是调用public void add(CD cd)方法
        db.add(new CD("def", "def", 4, "...", 60));
        db.add(new DVD("xxx", "aaa", 60, "...", 60));
        db.list();
    }

}
public class CD extends Item {   //ectends表示继承,继承父类Item,剩下代码没有改变

    private String title;
    private String artist;
    private int numOfTracks;
    private boolean gotIt; // 默认值为false
    private String comment;
    private int palyingTime;

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

    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

    public void print() {
        System.out.println("CD : " + title + ":" + artist);

    }

}
public class DVD extends Item {  //同样是继承父类Item,剩下代码没有改变

    private String title;
    private String director;
    private int numOfTracks;
    private boolean gotIt; // 默认值为false
    private String comment;
    private int playingTime;

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

    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

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

    }

}
public class Item {

    public void print() {

    }

}//Item类先什么也不做,为什么还能有结果呢?

输出结果

CD : abc:abc
CD : def:def
DVD : xxx :aaa

以前DateBase认识CD和DVD,管理CD和DVD,现在只认识Item,只管理Item。

public void add(Item item) {
        listItem.add(item);
    }
db.add(new CD("abc", "abc", 4, "...", 60));

为什么add里面new的CD可以被Item接收?

因为CD是Item的子类,对Datebase来说,他对Item的全部的认识是说,Item应该有一个print()函数,DateBase要的是你有print()函数就好了,具体是哪一个item,他不关心。但是CD里头也有print()函数。

把CD中的print()删掉并不会引起错误,因为他继承了Item的print()函数;
子类得到父类所有可访问的东西。看下面的例子

public class Item {

    public void print() {
        System.out.println("Item"); //为了看出变化,在Item设置输出一些东西
    }

}
public class CD extends Item {
 public static void main(String[] args) {
        CD cd = new CD("a", "A", 2, "...", 20);
        cd.print();   //CD中并没有print()函数,但是却可以运行,来看看结果

    }
    //注释掉原来CD的print()函数
//    public void print() {
//        System.out.println("CD : " + title + ":" + artist);
//
//    }

输出结果

Item

我们看到输出的是父类的print()函数,说明CD继承了Item的方法。

 public static void main(String[] args) {
        CD cd = new CD("a", "A", 2, "...", 20);
        cd.print();

    }
//把注释掉的CD类的print()函数弄回来,看看现在的print()是谁的
    public void print() {
        System.out.println("CD : " + title + ":" + artist);

    }

输出结果

CD : a:A

说明如果子类有和父类相同的方法时,会使用自己类里面的方法
同样子类当中有和父类一模一样的成员变量,那么父类的就会被隐藏了

来看看CD类中的title去向

public class Item {

    private String title;
    
    public void print() {
        System.out.println("Item");
    }

    public void setTitle(String title) {
        this.title = title;
    }
}
public class CD extends Item {

    private String title;
    private String artist;
    private int numOfTracks;
    private boolean gotIt; // 默认值为false
    private String comment;
    private int palyingTime;

    public CD(String title, String artist, int numOfTracks, String comment, int palyingTime) {
        super();
        this.title = title;  //自己类得到中的title得到title
        setTitle(title); //setTitle时父类的方法,title传递到父类中,由父类自己处理
        this.artist = artist;
        this.numOfTracks = numOfTracks;
        this.comment = comment;
        this.palyingTime = palyingTime;
    }

结论:父类的title有private,子类是无法访问的,但是可以通过父类本身的方法去访问,在谁的函数里指的成员变量就是谁的,如果子类和父类出现同名的成员变量,子类自己函数里面指的就是他自己的,那么在父类函数里指的就是父类的,他们之间没有任何联系。

尽量不要把成员变量变成protected,除非迫不得已

来看看怎么调用父类的函数

public class DVD extends Item {

    private String director;

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

    public static void main(String[] args) {

        DVD dvd = new DVD("a", "A", 2, ">>>", 20);
        dvd.print(); // 子类和父类同名的方法,在子类里面就调用子类自己的

    }

    public void print() {
        System.out.print("DVD ");
        //title是父类私有的,我们想输出title,用父类的函数来输出title好了
        //不建议用protected来修饰title,能不用就不用
        super.print(); // 想调用父类的print()要用super
        System.out.println(director);

    }

}
public class Item {

    private String title;
    private int numOfTracks;
    private boolean gotIt; // 默认值为false
    private String comment;
    private int palyingTime;

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

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

    public void setTitle(String title) {
        this.title = title;
    }
}

输出结果

DVD a
A
  • 子类的对象可以赋给父类的变量
    好像父类“车”,子类“自行车”和“汽车”,"车"的变量可以接收“自行车”和“汽车”的对象
    Vehicle v1 = new Vehicle();
    Vehicle v2 = new car();
    Vehicle v3 = new Bicyle();
  • 子类的对象可以传递给需要父类的函数
  • 子类的对象可以放在父类对象的容器里,比如上面的ArrayList<>。

多态变量

  • Java的对象变量是多态的,他们能保存不止一种类型的对象,像ArrayList<>
  • 他们可以保存的是声明类型的对象(item),或声明类型的子类的对象(cd和dvd)
 public void list() {
        for (Item item : listItem) {
            item.print();
            //声明类型就是item,传递过来得可能是dvd可能是cd,所以看的是实际管理的是谁,就执行谁的print();
            //实际管理的是cd,就做cd的print(),实际管理得是dvd,就做dvd的print(),而不一定是Item类里面的print
        }
    }
  • 当把子类的对象赋给父类的时候,就发生了向上造型。

什么是造型?
把一个类型的对象,赋给另外一个类型的变量,这个过程叫做造型。

造型cast

  • 子类的对象可以赋值给父类的变量
  • 注意!Java中不存在对象给对象赋值!!
  • 父类的对象不能赋值给子类的变量!
	Vechicle v;     
	Car c = new Car();  //创建一个Car的对象
	v = c;    //子类对象赋值给父类变量,可以!
	c = v;    //编译错误
  • 可以用造型
c = (Car)v;   //前提是v这个变量实际管理的是Car才行

再比如

		Item item = new Item("a", 2, false, "...");
        CD cd = new CD("A", "AA", 2, ">>>", 3);
        cd = item;   //错误,编译不通过
        item = cd;    //正确
Item item = new Item("a", 2, false, "...");
        CD cd = new CD("A", "AA", 2, ">>>", 3);
        item = cd;
        CD cc = new CD("W", "WW", 2, "<<", 4);
        cc = cd;  //同类型,可以
        cc = item;  //父类给子类,编译不通过
        cc = (CD)item;  //强制转化让item管理CD,编译无奈通过,但是item事实上并不管理CD类,运行失败,类造型异常

造型

  • 用括号围起类型放在值得前面
  • 对象本身并没有发生任何变化
  • 运行时有机制来检查这样的转化是否合理
  • ClassCastException(类造型异常)

向上造型

  • 拿一个子类的对象,当作父类来用
  • 向上造型是默认的,不需要运算符
  • 向上造型总是安全的

多态
比如声明类型就是item,传递过来得可能是dvd可能是cd,所以看的是实际管理的是谁,就执行谁的print();
实际管理的是cd,就做cd的print(),实际管理得是dvd,就做dvd的print(),而不一定是Item类里面的print()。
这样的过程叫多态。

函数调用的绑定

  • 当通过对象变量调用函数的时候,调用那个函数这件事情叫做绑定。
  • 静态绑定:根据变量的声明类型来决定
  • 动态绑定:根据变量的动态类型来决定
  • 在成员函数中调用其他成员函数也是通过this这个对象变量来调用的。
 public void list() {
        for (Item item : listItem) {
            item.print();  //编译的时候并不知道这个item管的是什么,
            //只有运行的时候才知道,运行的时候才知道的就是动态的。
            //对Java所有的成员函数的调用,都应该被看做是动态绑定
        }
    }

覆盖override

  • 子类和父类中存在名称和参数表完全相同的函数,这一对函数构成覆盖关系
  • 通过父类的变量调用存在的覆盖关系的函数时,会调用所管理的对象所属的函数
设计要求: 1. 设计实现一个出版物的输入输出系统,出版物包括书,CD和磁带,用户选择对某一个出版物输入相关信息,并将输入的信息显示。 2. 各出版物信息包括名字,作者或演唱者,出版社或唱片社,价格,出版日期等相关信息。 3. 使用循环来完成,以接受用户的循环操作。 4. 对于不合要求的输入,给出提示,允许再重新输入。 5. 当用户选择退出时,程序结束。 设计思路: 设计书,CD,磁带三个,每个含有名字,作者或演唱者,出版社或唱片社,价格,出版日期等相关信息。 由于这三个又相关的相同内容,故可设计一个含有公共信息的父。 class MyMedia{ String mediaName; //出版物名称 float price; //出版物价格 String press; //出版社(磁带发行商) String artist; //作者(演唱者) void mediaNameInput() //出版物名称输入 void mediaPriceInput(){ //出版物价格输入 void mediaPressInput(){ //出版社(磁带发行商)输入 void artistInput(){ //作者或演唱者输入 然后分别定义书,CD,磁带三个,并在各个子中添加新的成员变量。 class MyBook extends MyMedia{ //书子 String editor; //书的编辑 Date publishDate=null; //出版日期 String bookISBN; //书的ISBN } class MyCD extends MyMedia{ //CD String cdISRC; //CD的ISRC String cdPublisher; //CD的发行商 } class MyTape extends MyMedia{ //磁带子 String tapeISRC; } 相应改变各个子中的成员函数。 主程序中用下述语句输出选项供用户选择: System.out.println("\n请选择你要进行的操作(请输入1-4中人一个数字):\n" +"1:输入书的信息;\n" +"2:输入CD的信息;\n" +"3:输入磁带的信息;\n" +"4:退出系统;\n"); 用户输入的值保存于变量choice中,程序根据它的值分情况处理: switch(choice){ case 1: //选择为书 //要求输入书的名称,价格等信息的输入相关信息,然后程序输出这些信息 break; case 2: //选择为CD //要求输入CD的名称,价格等信息的输入相关信息,然后程序输出这些信息 break; case 3: //选择为磁带 //要求输入磁带的名称,价格等信息的输入相关信息,然后程序输出这些信息 break; default: //选择错误 continue_e=false; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值