类与对象
用类制造对象
对象(这只猫)(属性+服务 数据:属性或状态, 操作:函数)
- 表达东西或事件
- 运行时响应消息(提供服务)
类(猫)
- 定义所有猫的属性
- 就是Java中的类型
- 可以用来定义变量
(定义类)创建对象
- new VendingMachine();
- VendingMachine v = new VendingMachine();
- 对象变量是对象的管理者
- . 运算符→(类似点语法,但是这里是让对象执行方法)
- 学习调试方法
package vendingmachine;
//类:VendingMachine 制造对象:vm
public class VendingMachine {
int price = 80;;//(成员变量)
int balance;
int total;
void setPrice(int price)
{
void showPrompt()
{
System.out.println("Welcome");
}
void insertMomey(int amount)
{
balance = balance + amount;//在函数中可以直接写成员变量的名字来访问成员变量
}
void showBalance()
{
System.out.println(this.balance); // 等于balance
}
void getFood()
{
if( balance >= price) {
System.out.println("Here you are");
balance = balance - price;
total = total + price;
}
}
public static void main(String[] args) {
VendingMachine vm = new VendingMachine();
vm.showPrompt();
vm.showBalance();
vm.insertMomey(100);
vm.getFood();
vm.showBalance();
VendingMachine vm1 = new VendingMachine();
vm1.insertMomey(200);
vm.showBalance();
vm1.showBalance();
}
}
成员变量
- 类定义了对象中所具有的变量,这些变量称作成员变量
- 每个对象有自己的变量,和同一个类的其他对象是分开的
函数和成员变量
- 在函数中可以直接写成员变量的名字来访问成员变量
- 究竟访问的哪个对象,函数是通过对象来调用的
v.insertMoney 临时建立insertMoney()内部的成员变量和v(对象)之间的关系,让insertMoney中的成员变量等于此时指向的对象v的成员变量,这个联系通过this来连。
this
- this是成员函数的一个特殊的固有的本地变量,它表示这一次调用了这个函数的那个对象。
调用函数
- 通过. 运算符调用某个对象的函数
- 在成员函数内部直接调用自己(this)的其他函数
- 定义在函数内部的变量是本地变量
- 本地变量的生存期是对象的生存期和作用域都是函数内部
- 成员变量的生存期是对象的生存期,作用域是类内部的成员变量
对象初始化
变量的初始化是程序安全很重要的一环。一旦创建了一个对象,有什么手段可以保证其中的每一个成员变量都有确定的初始值呢?
Java提供了多种手段来保障对象创建时的初始化,包括给每个成员变量默认的“0”值、定义初始化和构造函数。
本课时还涉及了函数重载和用this()来调用其他构造函数的方式。
构造函数
- 如果有一个成员函数的名字和类的名字完全相同,则在创建这个类的每一个对象的时候回自动调用这个函数 —→构造函数
- 这个函数不能有返回类型
函数重载
- 一个类可以有多个构造函数,只有它们的参数表不同
- 创建对象的时候给出不同的参数值,就会调用不同的构造函数
- 通过this()还可以调用其他构造函数
- 一个类里的同名但参数表不同的函数构成了重载关系
package vendingmachine;
//类:VendingMachine 制造对象:vm
public class VendingMachine {
int price = 80;;
int balance = f();
int total;
VendingMachine() //构造函数(在构造的时候会被自动调用的函数)
{
total = 0;
}
VendingMachine(int price) //重载
{
this(); //可以用来调用另外一个没有参数的构造函数,但是只能在构造函数里出现,并且只能使用一次
this.price = price;
}
int f()
{
return 10;
}
void setPrice (int price)//让80price等于参数price 假设price参数=100,最终出来price= 100
{
this.price = price; //price在里面指向离他最近的price,即参数price
this.getFood();
}
void showPrompt()
{
System.out.println("Welcome");
}
void insertMomey(int amount)
{
balance = balance + amount;
showBalance();
//this.showBalance(); 两种表示方法相同,内部可以直接用this调,外部用对象调,用this 它的id不变
}
void showBalance()
{
System.out.println(balance);
}
void getFood()
{
if( balance >= price) {
System.out.println("Here you are");
balance = balance - price;
total = total + price;
}
}
public static void main(String[] args) {
VendingMachine vm = new VendingMachine();
vm.showPrompt();
vm.showBalance();
vm.insertMomey(100);
vm.getFood();
vm.showBalance();
VendingMachine vm1 = new VendingMachine(100);
vm1.insertMomey(200);
vm.showBalance();
vm1.showBalance();
}
}
类型自动转换:就是如果一个地方,比如函数的参数需要的是比较宽的类型的数据,比如double就比int来得宽,那么如果调用函数的时候给出了int值,是会被自动转换成double去调用函数的。
如果有两个函数重载,一个是double,一个是int,不会发生类型自动转换的。
对象交互
2.1对象交互
package clock;
public class Clock {
private Display hour = new Display(24); //Display类型的对象叫hour,要创建对象
private Display minute = new Display(60);
public void start() {
while(true) {
minute.increase();
if(minute.getValue() == 0) {
hour.increase();
}
System.out.printf("%02d:%02d\n", hour.getValue(),minute.getValue());
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Clock clock = new Clock();
clock.start();
}
}
//Clock是类,clock是对象,Display是clock对象的成员变量
//一个类里面的成员变量可以是其他类的对象,一个对象里面可以由其他对象组成的(其实我感觉不用硬理解,它说的也有问题)
package clock;
public class Display { //display是对象,有两个成员变量
private int value = 0;//成员变量
private int limit = 0;
public Display(int limit)
{
this.limit = limit;
}
public void increase() {
value++;
if(value == limit) {
value = 0;
}
}
public int getValue() {
return value;
}
public static void main(String[] args) {
Display d = new Display(24);
for(;;) {
d.increase();
System.out.println(d.getValue());
}
}
}
//Display是类。d是对象,value和limit是成员变量
解释:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XeyRzasw-1611367820154)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/48c1579e-dab6-4df9-b185-bbf8eb6be0a1/2020-11-30_10.52.12.png)]
package clock;
public class Clock {
private Display hour = new Display(24); //Display类型的对象叫hour,要创建对象
private Display minute = new Display(60);
public void start() {
while(true) {
minute.increase();
if(minute.getValue() == 0) {
hour.increase();
}
System.out.printf("%02d:%02d\n", hour.getValue(),minute.getValue());
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Clock clock = new Clock();
clock.start();
}
}
//Clock是类,clock是对象,Display是clock对象的成员变量
//一个类里面的成员变量可以是其他类的对象,一个对象里面可以由其他对象组成的(其实我感觉不用硬理解,它说的也有问题)
package clock;
public class Display { //display是对象,有两个成员变量
private int value = 0;//成员变量
private int limit = 0;
public Display(int limit)
{
this.limit = limit;
}
public void increase() {
value++;
if(value == limit) {
value = 0;
}
}
public int getValue() {
return value;
}
public static void main(String[] args) {
Display d = new Display(24);
for(;;) {
d.increase();
System.out.println(d.getValue());
}
}
}
//Display是类。d是对象,value和limit是成员变量
Java继承与多态
1.继承
原始的资料库程序
CD.java
package demo;
public class CD {
private String title;
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();
this.title = title;
this.artist = artist;
this.numofTracks = numofTracks;
this.playingTime = playingTime;
this.comment = comment;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
public void print() {
// TODO Auto-generated method stub
System.out.println("CD" +title+":"+artist);
}
}
Database.java
package demo;
import java.util.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();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Database db = new Database();
db.add(new CD("abc","abc",4,60,"..."));
db.add(new CD("abf","abc",4,60,"..."));
db.add(new DVD("xxx", "aaa", 60, "..."));
db.list();
}
}
DVD.java
package demo;
public class DVD {
private String title;
private String director;
private int playingTime;
private boolean gotIt = false;
private String comment;
public static void main(String[] args) {
// TODO Auto-generated method stub
}
public void print() {
// TODO Auto-generated method stub
System.out.println("DVD" +title+":"+director);
}
public DVD(String title, String director, int playingTime, String comment) {
//super();
this.title = title;
this.director = director;
this.playingTime = playingTime;
this.comment = comment;
}
}
DVD和CD中有很多几乎一样的代码
容器
顺序容器
容器是现代程序设计非常基础而重要的手段。
所谓容器,就是“放东西的东西”。数组可以看作是一种容器,但是数组的元素个数一旦确定就无法改变,这在实际使用中是很大的不足。一般意义上的容器,是指具有自动增长容量能力的存放数据的一种数据结构。在面向对象语言中,这种数据结构本身表达为一个对象。所以才有“放东西的东西”的说法。
Java具有丰富的容器,Java的容器具有丰富的功能和良好的性能。熟悉并能充分有效地利用好容器,是现代程序设计的基本能力。
我们首先学习的是顺序容器,即放进容器中的对象是按照指定的顺序(放的顺序)排列起来的,而且允许具有相同值的多个对象存在。
在一些书中,将容器(英文为collection或container)翻译为“集合”,由于数学中的集合(Set)也是一种特定的容器类型,我们认为将collection翻译为集合是不恰当的。所以我们只会使用容器一词。
对象数组
当数组的元素的类型是类的时候,数组的每一个元素其实只是对象的管理者而不是对象本身。因此,仅仅创建数组并没有创建其中的每一个对象!
集合
集合就是数学中的集合的概念:所有的元素都具有唯一的值,元素在其中没有顺序。
集合能用get()函数来获得某个位置上的元素吗?
不能。
首先在Java的HashSet类中没有定义get()方法,调用无效;
其次,作为数学意义上的具有无序性的集合,试图以线性的索引去获取其中的值是毫无意义的。
Hash
传统意义上的Hash表,是能以int做值,将数据存放起来的数据结构。Java的Hash表可以以任何实现了hash()函数的类的对象做值来存放对象。
Hash表是非常有用的数据结构,熟悉它,充分使用它,往往能起到事半功倍的效果。
继承
做一个公共的东西
我们把用来做基础派生其它类的那个类叫做父类、超类或者基类,而派生出来的新类叫做子类。Java用关键字extends表示这种继承/派生关系:
class ThisClass extends SuperClass {
//…
}
继承表达了一种is-a关系,就是说,子类的对象可以被看作是父类的对象。比如鸡是从鸟派生出来的,因此任何一只都可以被称作是一只鸟。但是反过来不行,有些鸟是鸡,但并不是所有的鸟都是鸡。如果你设计的继承关系,导致当你试图把一个子类的对象看作是父类的对象时显然很不合逻辑,比如你让鸡类从水果类得到继承,然后你试图说:这只本鸡是一种水果,所以这本鸡煲就像水果色拉。这显然不合逻辑,如果出现这样的问题,那就说明你的类的关系的设计是不正确的。Java的继承只允许单继承,即一个类只能有一个父类。
子类可以拥有父类的部分属性和方法
父类中的非私有属性(public,protected,default)和方法可以被子类继承拥有
由于访问权限带来的限制,子类无法直接访问私有属性和方法,必须通过父类提供的方法进行访问
对理解继承来说,最重要的事情是,知道哪些东西被继承了,或者说,子类从父类那里得到了什么。答案是:所有的东西,所有的父类的成员,包括变量和方法,都成为了子类的成员,除了构造方法。构造方法是父类所独有的,因为它们的名字就是类的名字,所以父类的构造方法在子类中不存在。除此之外,子类继承得到了父类所有的成员。
但是得到不等于可以随便使用。每个成员有不同的访问属性,子类继承得到了父类所有的成员,但是不同的访问属性使得子类在使用这些成员时有所不同:有些父类的成员直接成为子类的对外的界面,有些则被深深地隐藏起来,即使子类自己也不能直接访问。下表列出了不同访问属性的父类成员在子类中的访问属性:
public的成员直接成为子类的public的成员,protected的成员也直接成为子类的protected的成员。Java的protected的意思是包内和子类可访问,所以它比缺省的访问属性要宽一些。而对于父类的缺省的未定义访问属性的成员来说,他们是在父类所在的包内可见,如果子类不属于父类的包,那么在子类里面,这些缺省属性的成员和private的成员是一样的:不可见。父类的private的成员在子类里仍然是存在的,只是子类中不能直接访问。我们不可以在子类中重新定义继承得到的成员的访问属性。如果我们试图重新定义一个在父类中已经存在的成员变量,那么我们是在定义一个与父类的成员变量完全无关的变量,在子类中我们可以访问这个定义在子类中的变量,在父类的方法中访问父类的那个。尽管它们同名但是互不影响。
在构造一个子类的对象时,父类的构造方法也是会被调用的,而且父类的构造方法在子类的构造方法之前被调用。在程序运行过程中,子类对象的一部分空间存放的是父类对象。因为子类从父类得到继承,在子类对象初始化过程中可能会使用到父类的成员。所以父类的空间正是要先被初始化的,然后子类的空间才得到初始化。在这个过程中,如果父类的构造方法需要参数,如何传递参数就很重要了。(super(参数))
子类不可直接调用父类的private方法,可以通过父类的public(及其他子类可访问)方法和this间接使用父类private方法
database.java
package demo;
import java.util.ArrayList;
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);
// }
public void add(Item 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) {
// TODO Auto-generated method stub
Database db = new Database();
db.add(new CD("abc","abc",4,60,"...")); //Item子类的对象传进来于参数item不冲突(向上造型)
db.add(new CD("abf","abc",4,60,"..."));
db.add(new DVD("xxx", "aaa", 60, "..."));
db.list();
}
}
Item.java
package demo;
//父类要保证初始化两件事情,定义成员变量初始化和构造函数的初始化(不管有没有super)
public class Item {
//protected String title; 办法一
private String title;
private int playingTime;
private boolean gotIt = false;
private String comment;
//private子类不能碰,父类自己构造函数子类super调用去碰
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 setTitle(String title) {
this.title = title;
}
public void print() {
System.out.println(title);
}
}
CD.java
package demo;
public class CD extends Item{ //继承,CD成了Item的一个子类
// private String title;
private String artist;
private int numofTracks;
//自己创造的构造函数
public CD(String title, String artist, int numofTracks, int playingTime, String comment) {
super(title,playingTime,false,comment);//初始化是在item的构造函数中完成的,先做父类的初始化再做自己的
//this.title = title;
this.artist = artist;
this.numofTracks = numofTracks;
// this.playingTime = playingTime;
// this.comment = comment;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
CD cd = new CD("a","b", 2,2,"...");
cd.print();
}
// public void print() {
// // TODO Auto-generated method stub
// System.out.println("CD" +title+":"+artist);
// }
}
DVD.java
package demo;
public class DVD extends Item{
private String director;
public DVD(String title, String director, int playingTime, String comment) {
//这个过程中子类会自动去找父类的构造函数。没有super传函数就找不带参数的
super(title,playingTime,false,comment);
//this.title = title;
//子类中有相同的变量,在子类函数里面表示的就是子类自己的
setTitle("b");
this.director = director;
// this.playingTime = playingTime;
// this.comment = comment;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
DVD dvd = new DVD("a","b", 2,"...");
dvd.print();
}
public void print() {
// TODO Auto-generated method stub
System.out.println("DVD:");
super.print();
System.out.print(director);
}
}
多态
类定义了类型,DVD类所创建的对象的类型就是DVD。类可以有子类,所以由那些类定义的类型可以有子类型。在DoME的例子中,DVD类型就是Item类型的子类型。
子类型类似于类的层次,类型也构成了类型层次。子类所定义的类型是其超类的类型的子类型。
当把一个对象赋值给一个变量时,对象的类型必须与变量的类型相匹配,如:
Car myCar = new Car();
是一个有效的赋值,因为Car类型的对象被赋值给声明为保存Car类型对象的变量。但是由于引入 了继承,这里的类型规则就得叙述得更完整些:
一个变量可以保存其所声明的类型或该类型的任何子类型。
对象变量可以保存其声明的类型的对象,或该类型的任何子类型的对象。
Java中保存对象类型的变量是多态变量。“多态”这个术语(字面意思是许多形态)是指一个变量可以保存不同类型(即其声明的类型或任何子类型)的对象。
子类和子类型
- 类定义了类型
- 子类定义了子类型
- 子类的对象可以被当作父类的对象来使用
- 赋值给父类的变量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i0j5ltU7-1611368201611)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c269f206-892e-4558-9447-a6471f5a9d84/2020-12-19_9.36.15.png)]
- 传递给需要父类对象的函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AyznuqPT-1611368201614)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/666e909d-a325-4948-bf13-176d3d0f9210/2020-12-19_9.40.25.png)]
- 放进存放父类对象的容器里
子类的对象(CD,DVD的对象)就可以被放在父类容器(listitem)中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2HIVJl0L-1611368201616)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/9d7a41ff-261e-4aa8-964e-66d1bb610463/2020-12-19_9.49.12.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rzyN0pzA-1611368201618)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/69871479-9cb0-4ef9-81f6-a3f8a38ecb79/2020-12-19_9.45.17.png)]
多态,变量有多种形态
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lQ1LKUKy-1611368201619)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/2a782ec1-9976-4580-aa63-c3bcba610957/2020-12-19_9.56.41.png)]
每一个对象变量,静态类型(字面上的)和动态类型(当程序运行到这里时代表的是哪个对象类型)
多态变量的意思就是这个变量运行的时候它所管理的那个对象类型是会变化的
向上造型
把一个类型的对象,赋值给另外一个类型的变量
ClassCastException 类造型异常
造型cast
-
子类的对象可以赋值给父类的变量
-
Java中不存在对象对对象的赋值!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YgpwLsPc-1611368201621)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/9d109d18-8c51-4a1a-86e3-30c6978af1d2/2020-12-19_11.55.58.png)]
-
父类的对象不能赋值给子类的变量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p9DgzqvD-1611368201623)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/cecc579a-ccff-48b9-9377-652afd1b8813/2020-12-19_11.36.11.png)]
int i = (int)10.2;//类型转换
Item item = new Item("a",0,true, "...");
CD cd = new CD ("a", "a", 0, 0, "...");
item = cd;
CD cc = (CD)item;//造型转换
注释第三行会报错,没有赋值直接将item搞成CD会报错的
造型
对象类型来说,是造型,不是类型转换
- 用括号围起类型放在值的前面
- 对象本身并没有发生任何变化(CD还是CD即使用的item的方法)
- 所以不是“类型转换”
- 运行时ClassCastException 类造型异常检查是否合理
向上造型
- 拿一个子类的对象,当作父类的对象来用
- 向上造型是默认的,不需要运算符
- 向上造型总是安全的
假设现有4个类:Person、Teacher、Student和PhDStudent。Teacher 和Student都是Person的子类,PhDStudent是Student的子类。以下的赋值语句哪些是合法的,为什么?:
Person p1 = new Student();
Person p2 = new PhDStudent();
PhDStudent phd1 = new Student();
Teacher t1 = new Person();
Student s1 = new PhDStudent();
s1 = p1;
s1 = p2;
P1 = s1;
t1 = s1;
s1 = phd1;
Phd1 = s1;
1 2 5 8 10
10无意义,虽然可以通过赋值运算,让s1和phd1同时管理一个对象,但是无法管理父类对象Student。
多态
如果子类的方法覆盖了父类的方法,我们也说父类的那个方法在子类有了新的版本或者新的实现。覆盖的新版本具有与老版本相同的方法签名:相同的方法名称和参数表。
因此,对于外界来说,子类并没有增加新的方法,仍然是在父类中定义过的那个方法。
不同的是,这是一个新版本,所以通过子类的对象调用这个方法,执行的是子类自己的方法。
覆盖关系并不说明父类中的方法已经不存在了,而是当通过一个子类的对象调用这个方法时,子类中的方法取代了父类的方法,父类的这个方法被“覆盖”起来而看不见了。
而当通过父类的对象调用这个方法时,实际上执行的仍然是父类中的这个方法。
注意我们这里说的是对象而不是变量,因为一个类型为父类的变量有可能实际指向的是一个子类的对象。(title)
通过父类的变量调用存在覆盖关系的函数时,会调用变量当时所管理的对象所属的类的函数
当通过对象变量调用一个方法时,究竟应该调用哪个方法,这件事情叫做绑定。绑定表明了调用一个方法的时候,我们使用的是哪个方法。
绑定有两种:一种是早绑定,又称静态绑定,(根据变量的声明类型来决定)这种绑定在编译的时候就确定了;
另一种是晚绑定,即动态绑定。动态绑定在运行的时候根据变量当时实际所指的对象的类型动态决定调用的方法。Java缺省使用动态绑定。
public Item(String title, int playingTime, boolean gotIt, String comment) {
super();
this.title = title;
this.playingTime = playingTime;
this.gotIt = gotIt;
this.comment = comment;
}
在成员函数中调用其他成员函数也是通过this这个对象变量来调用的
单根结构
都继承于Object
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bhN499jX-1611368201625)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/8d54d959-4a50-4163-b04d-a4a851e3bd28/2020-12-19_8.12.25.png)]
Object类的函数
查看object类中的函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h4OQEcby-1611368201627)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/6fe344e6-a3c1-46bc-994b-6f65d1427cc8/2020-12-19_8.15.46.png)]
- toString() 把对象转化成字符串
子类中可以直接调用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-idzlpOpc-1611368201628)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/69efed8f-396e-4a45-8ce7-de02b7a3dbab/2020-12-19_8.16.38.png)]
Source中列出来了toString
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eoKLOtYu-1611368201630)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/35d3e584-586c-4c37-af04-52afe857230f/2020-12-19_8.29.08.png)]
- equals()
作用:比较两个对象内容是否相同,==无法比较,只能比较这两个变量是否管理着同一个对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZIKjZeZp-1611368201632)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f27994e5-0482-4bf1-9e5b-36da8fb83336/2020-12-19_8.34.53.png)]
因为我们使用的是Object的equals,所以不能真正判断内容是否相同,要创建自己的equals
Source中创建一个equals
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HBEJduXF-1611368201638)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/ad62995a-4ea5-47e5-8349-3c8336ae0eb6/2020-12-19_8.53.53.png)]
@override是用来检查现在写的函数是覆盖类父类的函数,要与Object里的方法相同,否则报错
如果把@override删了,现在的函数不和父类写的一样,那么就根本不会进现在这个函数
新的拓展类型
新建一个子类,直接继承父类,可扩展性
最终代码:
DataBase.java
package demo;
import java.util.ArrayList;
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);
// }
public 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) {
// TODO Auto-generated method stub
// Object o = new Object();
// o.
// int i = (int)10.2;//类型转换
//
// Item item = new Item("a",0,true, "...");
// CD cd = new CD ("a", "a", 0, 0, "...");
// item = cd;
// CD cc = (CD)item;//造型转换
//
Database db = new Database();
db.add(new CD("abc","abc",4,60,"..."));
db.add(new CD("abf","abc",4,60,"..."));
db.add(new DVD("xxx", "aaa", 60, "..."));
db.add(new VideoGame("ddd", 10, true, "...", 4));
db.list();
}
}
结果:
abc
abf
DVD:
b
aaaVideoGameddd
CD.java
package demo;
public class CD extends Item{ //继承,CD成了Item的一个子类
// private String title;
private String artist;
private int numofTracks;
//自己创造的构造函数
public CD(String title, String artist, int numofTracks, int playingTime, String comment) {
super(title,playingTime,false,comment);//初始化是在item的构造函数中完成的,先做父类的初始化再做自己的
//this.title = title;
this.artist = artist;
this.numofTracks = numofTracks;
// this.playingTime = playingTime;
// this.comment = comment;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
CD cd = new CD("a","b", 2,2,"...");
CD cd1 = new CD("a","b", 2,2,"...");
System.out.println(cd.equals(cd1));
// cd.print();
// String s = "aa" + cd;
// System.out.println(s);
}
@Override //是覆盖类父类的函数,要与Object里的方法相同
public boolean equals(Object obj) {
// TODO Auto-generated method stub
//return super.equals(obj);
CD cc = (CD)obj;//向下构造
return artist.equals(cc.artist);
}
@Override
public String toString() {
return "CD [artist=" + artist + ", numofTracks=" + numofTracks + ", toString()=" + super.toString() + "]";
}
// public void print() {
// // TODO Auto-generated method stub
// System.out.println("CD" +title+":"+artist);
// }
}
DVD.java
package demo;
public class DVD extends Item{
private String director;
public DVD(String title, String director, int playingTime, String comment) {
//这个过程中子类会自动去找父类的构造函数。没有super传函数就找不带参数的
super(title,playingTime,false,comment);
//this.title = title;
//子类中有相同的变量,在子类函数里面表示的就是子类自己的
setTitle("b");
this.director = director;
// this.playingTime = playingTime;
// this.comment = comment;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
DVD dvd = new DVD("a","b", 2,"...");
dvd.print();
}
public void print() {
// TODO Auto-generated method stub
System.out.println("DVD:");
super.print();
System.out.print(director);
}
}
Item.java
package demo;
//父类要保证初始化两件事情,定义成员变量初始化和构造函数的初始化(不管有没有super)
public class Item {
//protected String title; 办法一
private String title;
private int playingTime;
private boolean gotIt = false;
private String comment;
//private子类不能碰,父类自己构造函数子类super调用去碰
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 setTitle(String title) {
this.title = title;
}
public void print() {
System.out.println(title);
}
}
VideoGame.java
package demo;
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;
// TODO Auto-generated constructor stub
}
@Override
public void print() {
// TODO Auto-generated method stub
System.out.print("VideoGame");
super.print();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}