《JavaSE》------20.语法实践项目【图书管理系统】

目录

前言

一、图书管理系统成果展示

1.1 管理员:

1.2 普通用户:

二、 图书管理系统框架的搭建

2.1 book包

2.1.2 BookList类

2.2 operation包

2.2.0 IOperation接口

2.2.1 AddOperatoon类

2.2.2 FindOperation类

2.2.3 DelOperation类

2.2.4 ShowOperation类

2.2.5 BorrowedOperation类

2.2.6 ReturnOperation类

2.2.7 ExitOperation类

2.3 User包

2.3.1 User类(抽象类)

2.3.2 Administrator类

2.3.3 NormalUser类

2.2.4菜单功能选择的框架实现

Main类


前言

学完了javaSE语法,今天就带大家一起实现一个用Java语言写的图书管理系统吧。我们简单讲讲这个图书管理系统的功能。非常适合刚刚学完语法的小白哦~~~~~

我们先来简单的展示一下我们管理系统的页面。不同的身份对应不同的功能。

一、图书管理系统成果展示

开始菜单你需要输入你的姓名:

 假如说我叫祁思妙想

回车之后, 你可以确认你的身份,假如你是管理员你就输入1,假如你是普通用户你就输入0。

我们先来看看管理员的菜单都有什么功能:

1.1 管理员:

假如你是管理员,你可以进行

①查找图书 ②新增图书 ③删除图书 ④显示图书 ⑤退出系统。


显示图书功能示例:输入4,回车后便会显示现在我们书架上已有的图书。我们默认包括了以下三本书,每一本书都有书名,作者,价格,类型,是否被借出等指标。每一个功能完成之后会自动跳转会菜单界面,可以继续选择功能。


 查找图书功能示例:输入1回车之后,进入查找图书功能。你可以输入你想要查找的书籍的书名,如果找到了会显示出这本书的各种指标,如果没找到会告诉你没有找到。


新增图书功能示例:输入2回车后,进入新增图书功能,你需要输入新增书的书名,作者,价格,类型。回车后,系统会提示你添加成功,并且会告诉你书架此时有几本书。新增的图书默认是未被借出。


删除图书功能示例:输入3回车,之后输入你要删除的书名,若书架上没有你的书名,则返回,没找到你要删除的图书,若有则返回删除成功,并显示此时书架有多少本书。删除后再次显示图书,可以发现已经删除成功!

退出系统功能示例:输入0回车后,程序停止运行。

1.2 普通用户:

普通用户的功能有

①查找图书 ②借阅图书 ③归还图书 ④退出系统

假如我现在名字叫做祁早贪黑。我是普通用户。则可以进行以下操作。

 其中查找图书功能,与退出系统功能与管理员身份的功能是一样的,我们就不再演示了。我们看


借阅图书功能示例:输入2回车之后,会提示你输入你想借阅图书的名字,假设要借西游记,回车后返回,借阅成功!,若书架中没有你想借阅的图书,则会返回很抱歉,没有找到你想借阅的图书。我们再查找西游记这本图书,最后面的指标已经是被借出了,若你想借阅的图书已经被借阅,则会返回,图书已经被借阅,您无法再次借阅。


 归还图书功能示例:输入3回车之后,会提示你输入你想归还图书的名字,假设要借西游记,回车后返回,归还成功!,若书架中没有你想归还的图书,则会返回很抱歉,没有找到你想归还的图书。我们再查找西游记这本图书,最后面的指标变成了未被借出。

 以上就是本次我们要编程的Java版本的一个简易的图书管理系统!!!!

接下来我们看看编写这个图书管理系统需要进行的每一步操作吧!!!!!

了解了我们这个图书管理系统的各个功能之后,相信小伙伴们已经对我们这个图书管理系统有了初步的认知。里面用到了许多我们JavaSE的基础语法,例如:分支循环,数组,类与对象,封装,继承,多态,字符串.......编写这个简易的图书管理系统,有效的复习了我们之前学习过的Java的基础语法知识。

二、 图书管理系统框架的搭建

首先我们在IDEA中新建一个项目,项目名称我们设置成BookMS(book manage system)。

1. 在包src中创建一个主类命名为Main类。我们所有的程序都要在这个类中运行。

2.在包src中以包的形式创建和书相关的包book包,和身份相关的包user包,和操作相关的包operation包等等。因为我们要通过不同的包去组织这些类,在同一包中放同一类型的类。


2.1 book包

在这个包里我们要创建如下类

2.1.1 Book类

成员变量:

1.①在book包中创建一个Book类,用来抽象出一本数。其中包含字符串String类型书名、作者、类型等变量,整型int类型的价格变量布尔类型的是否被借出flase未被借出,ture被借出变量,这些成员变量我们对其进行封装用private修饰。保证程序的安全性。

成员方法:

②(快捷创建)并创建getter,setter方法,方便初始化和获取封装的这些变量的内容,可以对这些成员变量进行初始化以及得到这些被封装的变量的值;(一定是快捷键创建哦)不会快捷创建这些方法的小伙伴可以去看看之前讲Java封装的文章,里面详细介绍了创建Getter,Setter等方法的快捷键用法。

③(快捷创建)创建成员变量对应的构造方法,方便后续为实例化出来的对象(每本书)赋值(也是快捷键创建哦,文章类与对象中讲过),在new一个新的书这个对象时。让我们对其成员变量进行初始化,由于是否被借出是boolean类型。默认是flase代表没有被借出,因此我们不对它进行初始化。当然这里面的有些方法可能是我们用不到的,但我们就顺手写了。

④(快捷创建)创建toString方法,方便后面显示图书(也是快捷健创建,也在面向对象系列的文章里。这是为了能直接打印数组名,来打印数组内容,涉及到方法的重写。我们对快捷创建出来的内容进行了修改,以达到我们想要达到的效果)

以下是Book类中的所有代码:

package book;public  class Book {//抽象出书的成员变量private String name;//书名private String author;//作者private int price;//价格private String type;//类型private boolean isBorrowed;//是否被借出public Book(String name, String author, int price, String type) {this.name = name;this.author = author;this.price = price;this.type = type;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public int getPrice() {return price;}public void setPrice(int price) {this.price = price;}public String getType() {return type;}public void setType(String type) {this.type = type;}public boolean getBorrowed() {return isBorrowed;}public void setBorrowed(boolean borrowed) {isBorrowed = borrowed;}@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", author='" + author + '\'' +", price=" + price +", type='" + type + '\'' +
//                ", isBorrowed=" + isBorrowed +((isBorrowed == true) ? " 被借出" : " 未被借出")+'}';}
}

本类中的代码比较简单,将书抽象出来,到时候我们就可以new出许多不同的书了

需要注意的两个地方有

1.定义布尔类型时一定是boolean来定义。而不是Boolean,在我编写代码的时候就犯了这个错,导致布尔变量isBorrowed的默认值编程了null。而不是布尔boolean类型的默认值flase

2.在toString时修改其中内容时用到的三目运算符,要注意条件要添加括号哦!!! 最后再总体加给括号。


2.1.2 BookList类

1.在book包中创建一个BookList类

成员变量:

①创建一个Book类型的数组(就是我们上面定义的Book类)(这个数组中存的就是由Book类实例化出来的对象,也就是每一本书,这个就初步组成了一个书架)。并分配内存,我们初步定义可存的Book类型变量为十个。

②创建一个计数器变量bookCount来表示实际放的书的个数。

private Book[] books = new Book[10];     //定义一个Book类型的数组,分配十块空间,用来存放十本书

private int bookCount;       //来记录当前实际放的书的个数

//封装是为了避免该变量与其他包的变量弄混,保证程序的安全性

成员方法:

①(快捷创建)创建BookList构造方法。对里面的成员变量也就是Book类型的数组中的Book类型的对象进行初始化,以及对 bookCount 这个变量进行初始化。我们初始时放入三本书。因此将bookCount的数值初始化为3。

②(自己创建,这是数组需要自己创建,用来操作数组中的每个元素)创建getBook方法和setBook方法代表得到书架上的某本书和在书架中某一位置放一本书。

public Book getBooks(int pos) {

     return books [pos] ;

}

public void setBooks(int pos, Book book) {

     books [ pos ] = book;

}

③(快捷创建)创建getBookCount和setBookCount方法,用来设置和得到封装的变量bookCount的值

public int getBookCount() {

       return bookCount;

}

public void setBookCount(int bookCount) {

       this.bookCount = bookCount;

}

以下是BookList类 中的所有代码:

package book;public class BookList {//定义一个书架类,用来存放许多本书private Book[] books = new Book[10];//定义一个Book类型的数组,分配十块空间,用来存放十本书private int bookCount;//来记录当前实际放的书的个数public BookList() {//构造方法来初始化成员this.books[0] = new Book("三国演义","罗贯中",50,"小说");this.books[1] = new Book("西游记","吴承恩",51,"小说");this.books[2] = new Book("红楼梦","曹雪芹",49,"小说");this.bookCount = 3;}public Book getBooks(int pos){//得到数组中某一本书return books[pos];//返回数组中某一本书}public void setBooks(int pos, Book book){//在书架某个位置里放一本书。this.books[pos] = book;}public int getBookCount() {return bookCount;}public void setBookCount(int bookCount) {this.bookCount = bookCount;}
}

本类中, 也比较简单,稍有难度的就是

1.成员变量类型为之前创建的Book类。并创建了Book类型的数组,那么它存储的元素都是Book类型了,那么就可以存储由Book类new出来的对象。存储许许多多的书了。

2.值得一提的还有setBooks和getBooks这两个方法。这不是由快捷生成的,由于是数组。快捷生成的get和set达不到我们需要的功能。因此我们要自己创建这两个成员方法。目的是从书架Book类型的数组中取书(得到这个Book类型的数组元素)和放书(设置书,在?Book类型数组中存放一我们想存的书籍)。

3.BookList这个构造方法。这个构造方法没有参数的传递。目仅仅是为了初始化我们的成员变量。由于默认的书籍和数目都是我们已知的,因此不需要传入而赋值,只需要在内容中直接初始化我们的成员变量就可以了


2.2 operation包

在这个包里我们要创建如下接口和类,插入的代码就是那个接口或者类中所有的代码。

2.2.0 IOperation接口

0.创建接口,由于这些操作都是对于书架BookList的,因此我们可以把它们规范起来,以接口的形式进行定义,创建一个IOperation接口

public interface IOperation {

      void work (BookList bookList);

}

让下面的添加图书,查找图书,删除图书,显示图书,借阅图书,归还图书,退出系统这些类去实现这个接口。其中的work方法便是重写了这个接口中的work方法。到时候我们在User中管理员类和普通用户类中创建这个接口类型的数组。存入对应的功能,便可以用输入进去的数字(下标)来实现对应的某个功能了。这应该也算多态的一种吧,引用不同的对象,调用同一个方法,呈现不同的效果。

package Operation;import book.BookList;public interface IOperation {void work (BookList bookList);
}

因为这个包内都是一些功能方法,因此我们可以在这个包内创建一个接口。用于实现多态。

1.这个包内其他所有类来实现这个接口。并重写接口中的方法。到时候只需要调用接口中的方法便可以访问实现这个接口的所有功能方法中的这个方法了。

2.我们在User用户类中就可以创建一个接口类型的数组,里面分别存储这些Operation包内除接口外的功能方法。 这样我们就可以利用这个数组,传入下标后,来实现在菜单中输入数字几,从而调用不同的方法。


2.2.1 AddOperatoon类

1.添加图书,创建一个AddOperatoon类,用于添加图书。创建一个work方法,传入BookList类型的参数。将你要添加的图书放入书架。

package Operation;import book.Book;
import book.BookList;
import java.util.Scanner;
public class AddOperation implements IOperation{@Overridepublic void work(BookList bookList) {System.out.println("添加图书!");Scanner scanner = new Scanner(System.in);System.out.println("请分别输入你想添加的图书的书名,作者,价格,类型:");System.out.println("书名:");String name = scanner.nextLine();System.out.println("作者:");String author = scanner.nextLine();System.out.println("价格:");int price = scanner.nextInt();scanner.nextLine();  //这里标记重点回顾!!!!!!!!!!!!!System.out.println("类型:");String type = scanner.nextLine();Book book = new Book(name,author,price,type);int currentCount = bookList.getBookCount();for (int i = 0; i< currentCount; i++){Book book1 = bookList.getBooks(i);if (book1.getName().equals(name)){System.out.println("书架已经有这本书了,不需要再次添加!!!");return;}}bookList.setBooks(currentCount,book);bookList.setBookCount(currentCount+1);System.out.println("添加成功!");System.out.println("此时您可操作的图书有 " + bookList.getBookCount() + " 本!");}
}

本类是一个功能方法类。是为了实现菜单中的添加图书的功能。

我们将这个业务的功能写在重写方法work方法中。

1.传入BookList类型的参数bookList。传入这个参数的目的是为了调用这个参数中的成员变量。对其进行操作。如获取书架中书的数目。从书架中得到某一本书,或在书架中放入某一本书。

2.添加某本书,在本系统中,需要添加书名,书的作者,书的价格,书的类型。等四个书的成员变量,因此我们首先用sout打印提示词,之后定义四个变量。并用Scanner来从键盘输入来给变量赋值,之后在new好一本书的时候传入,利用已经建好的构造方法来初始化book的成员变量。这样新的book就创建好了。

3.用for循环遍历书架中Book数组,我们利用BookList中的getBooks方法来获取书架中的每本书,并将他存入我们新建的Book类型变量中,在比对书架中已有的图书的名字,如果相等,则书架中已有这本书,则不需要再次添加return返回。如果循环完了都没有相等的,那么我们就利用setBook方法来在bookList中存入我们定义的这本书。下标为书架中已有的书的个数。之后我们更新一下bookCount的数值,让它为currentCount+1。最后添加提示语。添加图书成功!

易错:

1.在我编写代码时,不小心添加图书时将

bookList.setBooks(currentCount,book);

写成了

 bookList.setBooks(currentCount+1,book);

我们要时刻注意下标是从0开始的,而书的数目是从1开始的,因此下标为currentCount时,就已经是数组中的空余的位置了。不能再加1,否则会将存储的位置存储错误。

2.当书架已经有这本后,一定要return,不然还会往下执行,将这本书再次添加形成重复的数据。


2.2.2 FindOperation类

2.查找图书,创建一个FindOperation类,用于查找图书,创建一个work方法,传入BookList类型的参数。将你要查找的图书从书架找到

package Operation;import book.Book;
import book.BookList;
import java.util.Scanner;public class FindOperation implements IOperation{public void work(BookList bookList){System.out.println("查找图书!");Scanner scanner = new Scanner(System.in);System.out.println("请输入你要查找的图书名:");String name = scanner.nextLine();int currentCount = bookList.getBookCount();for (int i = 0; i< currentCount; i++){Book book = bookList.getBooks(i);if (book.getName().equals(name)){System.out.println("找到了你!!!");System.out.println(book);return;}}System.out.println("很抱歉,没找到你想查找的书籍!");}
}

本类是一个功能方法类。是为了实现菜单中的查找图书的功能。可以说是添加图书的简化版本。如果你看懂了添加图书,那么查找图书就是小菜一碟了

1.我们这个查找图书的功能是通过比对书名来查找。如果书架中的书名与你输入的书名相等,那么就找到了你想要查找的书名,如果循环下来都没有相等的,那么就没有找到你想要的书籍。 代码非常简介就不细说了。

易错:

1.唯一要注意的是不要把最后没找到要查找的书籍的提示语放到循环之内。要放到循环之外,遍历完了数组都没有找到。此时再提示没有找到,这样才合理。 


2.2.3 DelOperation类

3.删除图书,创建一个DelOperation类,用于删除图书,创建一个work方法,传入BookList类型的参数。将你要删除的图书从书架中删除。

package Operation;import book.Book;
import book.BookList;
import java.util.Scanner;public class DelOperation implements IOperation{public void work(BookList bookList){int currentCount = bookList.getBookCount();if (currentCount == 0){System.out.println("书架为空,不能再移除图书了!!!");return;}Scanner scanner = new Scanner(System.in);System.out.println("请输入你要移除图书名:");String name = scanner.nextLine();int index = -1;for (int i = 0; i< currentCount; i++){Book book = bookList.getBooks(i);if (book.getName().equals(name)){index = i;break;}}if (index == -1){System.out.println("很抱歉,没找到你想删除的书籍!");return;}for (int i = index; i < currentCount; i++){Book book1 = bookList.getBooks(i+1);bookList.setBooks(i,book1);}System.out.println("删除成功!!!!");bookList.setBookCount(currentCount-1);System.out.println("如今您可操作的图书有 " + bookList.getBookCount() + " 本!");}
}

本类是一个功能方法类。是为了实现菜单中的移除图书的功能。

1.类似的我们输入书名,再遍历书架找到移除的书名。找到之后我们将这个书后面的所有书都往前移动一位。这就相当于在书架上将这本书拿走了。没找到则在循环外sout提示词没找到。

2.为了方便代码观赏,这里在找到与之对应的名称的图书之后巧用了临时变量index。要记得找到后是break跳出循环。

当然也可以写成这样的形式:

package Operation;import Book.Book;
import Book.BookList;import java.util.Scanner;public class DelOperation implements IOperation{@Overridepublic void work(BookList bookList) {System.out.println("请输入你想移除的图书的书名:");Scanner scanner = new Scanner(System.in);String name = scanner.nextLine();int currentBooks = bookList.getBookCount();int i;for(i = 0; i<currentBooks; i++ ){if (bookList.getBooks(i).getName().equals(name)){for (; i<currentBooks-1; i++){//为了避免数组越界,因此i<currentBooks-1;,这样虽然导致移除最后一本图书是进不来循环//但是我们将bookList.setBookCount(currentBooks-1);不影响显示图书和其他功能。//在用户眼里是被删除了的。Book book = bookList.getBooks(i+1);bookList.setBooks(i,book);}bookList.setBookCount(currentBooks-1);System.out.println("删除成功!!!");System.out.println("此时书架上共有 " + bookList.getBookCount() + " 本书供您操作!");return;}}System.out.println("很抱歉,没有找到你想要移除的图书!");}
}

此时找到后,移除完是return。直接跳出这个方法。

易错:

1.找到要移除的书之后,在将这本书后面的书统一往前移的过程中。一定是i<currentBooks-1 。如果i下标访问的是最后一本书,虽然没有进入循环,但是由于我们将bookCount的值修改了

bookList.setBookCount(currentBooks-1);

因此不影响显示图书和其他功能。在用户眼里是被删除了的。如果要添加则直接覆盖上去就行了。


2.2.4 ShowOperation类

4.显示图书,创建一个ShowOperation类,用于显示图书,创建一个work方法,传入BookList类型的参数。将书架中的图书显示出来。

package Operation;
import book.Book;
import book.BookList;public class ShowOperation implements IOperation{public void work(BookList bookList){System.out.println("展示图书!!!!");int currentCount = bookList.getBookCount();for (int i = 0; i< currentCount; i++){Book book = bookList.getBooks(i);System.out.println(book);}System.out.println("共有"+bookList.getBookCount()+"本书!");}
}

 本类是一个功能方法类。是为了实现菜单中的显示图书的功能。

1.由于我们已经用toString方法进行了方法的重写。首先得到书架上的书的数目,之后直接遍历书架sout打印book即可。非常简单,基本不会错。


2.2.5 BorrowedOperation类

5.借阅图书,创建一个BorrowedOperation类,用于借阅图书,创建一个work方法,传入BookList类型的参数。将书架中的图书借阅出来。

package Operation;import book.Book;
import book.BookList;
import java.util.Scanner;public class BorrowOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("请输入你想要借阅的图书的名字:");Scanner scanner = new Scanner(System.in);String name = scanner.nextLine();int currentCount = bookList.getBookCount();for (int i = 0; i< currentCount; i++){Book book = bookList.getBooks(i);if (book.getName().equals(name)){if (book.getBorrowed()){System.out.println("图书已经被借阅,您无法再次借阅");return;}book.setBorrowed(true);System.out.println("借阅成功!!!");return;}}System.out.println("很抱歉,没有找到你想借阅的图书");}
}

  本类是一个功能方法类。是为了实现菜单中的借阅图书的功能。


2.2.6 ReturnOperation类

6.归还图书,创建一个ReturnOperation类,用于归还图书,创建一个work方法,传入BookList类型的参数。将书架中的图书归还。

package Operation;import book.Book;
import book.BookList;
import java.util.Scanner;public class ReturnOperation implements IOperation {public void work(BookList bookList){System.out.println("请输入你想要归坏的图书的名字:");Scanner scanner = new Scanner(System.in);String name = scanner.nextLine();int currentCount = bookList.getBookCount();for (int i = 0; i< currentCount; i++){Book book = bookList.getBooks(i);if (book.getName().equals(name)){book.setBorrowed(false);System.out.println("归还成功!!!");return;}}System.out.println("很抱歉,没有你想要归还的图书");}
}

 本类是一个功能方法类。是为了实现菜单中的归还图书的功能。 


2.2.7 ExitOperation类

7.退出系统,创建一个ExitOperation类,用于退出系统,创建一个work方法,传入BookList类型的参数。用于退出系统。

package Operation;import book.Book;
import book.BookList;public class ExitOperation implements IOperation {public void work(BookList bookList){System.out.println("退出系统!!!欢迎下次光临!!!");int currentCount = bookList.getBookCount();for (int i = 0; i< currentCount; i++){bookList.setBooks(i,null);}bookList.setBookCount(0);System.exit(0);}
}

 本类是一个功能方法类。是为了实现菜单中的退出图书图书系统的功能。

System.exit(0);直接这样就可以了,不过我们既然传入了BookList参数,因此我们可以将书架清空,都置成空指针。然后将书架中书的数目设置成0。然后再退出系统。也是比较简单。


2.3 User包

在这个包里我们要创建如下类

2.3.1 User类(抽象类)

由于管理员,普通用户都是用户,我们可以将用户定义为一个父类User。

成员变量:

①创建字符串变量name。并创建构造方法对其初始化。之后让管理员和普通用户去继承它。

②创建接口类型数组,存储实现接口的各种方法,如 AddOperatoon,FindOperation,ShowOperation等等这些方法,到时利用动态绑定只需要输入对应的数字,便可以实现这些功能。

成员方法:

①创建meau方法,由于子类都需要用到meau方法,来打印菜单,因此父类需要这个方法,到时候可以实现重写,动态绑定,之后发生多态。也就是不同用户调用这个方法呈现出的结果不同。由于meau在父类中写不写都一样,因此我们可以将这个方法用abstract修饰。那么这个类也需要用abstruct修饰。将这个User类也该为抽象类。不知不觉中,我们就体会到了抽象类的作用。

②创建构造方法,用来初始化name这个成员变量。

③创建doOperation方法,用来传入用户选择的某个功能的对应的数字和书架。再由数组iOperations[下标],去接收这个数字,并调用这个类中的work方法。这样就搭建起了实现各种功能的框架。

以下是User类(抽象类)中的所有代码:

package User;
import Operation.IOperation;
import book.BookList;abstract public  class User {protected String name;public IOperation[] iOperations;//接口类型的数组public User(String name) {this.name = name;}abstract public int menu();public void doOperation(int choice, BookList bookList){iOperations[choice].work(bookList);}
}

 本类是在用户包中创建的一个User父类 。它的作用是引申出不同的身份,例如我们这个系统中的普通用户和管理员这个身份作为子类。去继承这个User父类。这样我们就可以进行向上转型,动态绑定来实现多态。传入不同的身份,来打印不同的菜单。并且建立了doOperation方法。用来在不同身份下,使不同的功能方法得到实现。

易错点:

1.由于在它的子类管理员和普通用户类还会使用name这个成员变量,因此我们可以不对成员变量name进行修饰,或者用protected来进行修饰。

注意此时我们并没有给这个接口类型数组进行赋值。


2.3.2 Administrator类

定义一个Administrator类代表管理员,作为子类继承父类User,继承后要帮助父类进行构造,在这里还有一个专属于管理员的菜单。 

成员变量:已经继承了父类User的成员变量,且无需有新的成员变量。因此只需要一个构造方法,帮助继承父类的成员变量进行初始化。

成员方法:

①创建构造方法,用来初始化从父类继承下来的成员变量。在用户选择管理员身份时,会new一个管理员对象,此时便会自动给这个对象进行初始化。以便于后续调用这个对象中的一些变量和方法。

②创建menu方法,重写父类的menu菜单。并sout出管理员的菜单,返回值类型为int类型,并return choice。便于后续在Main函数接收这个数值来调用不同的功能方法。

以下是Administrator类中的所有代码:

package User;import Operation.*;
import java.util.Scanner;
public class Administrator extends User {public Administrator(String name) {super(name);this.iOperations =new IOperation[]{new ExitOperation(),new FindOperation(),new AddOperation(),new DelOperation(),new ShowOperation(),};}@Overridepublic int menu() {System.out.println("***************************");System.out.println("hello! "+this.name+" 欢迎来到管理员菜单");System.out.println("1.查找图书");System.out.println("2.新增图书");System.out.println("3.删除图书");System.out.println("4.显示图书");System.out.println("0.退出系统");System.out.println("***************************");System.out.println("请输入你的操作:");Scanner scanner = new Scanner(System.in);int choice = scanner.nextInt();return choice;}
}

本类是用户User类的一个子类,管理员类,它的作用是使用户可以使用管理员身份来运行这个程序。这样会实现不同的功能。

易错点:

1.由于父类有name的构造方法,因此在子类中也要有构造方法,对继承父类来的name变量进行构造。

2.用this.去引用父类中的接口类型数组iOperations。并对其初始化,输入你想实现的功能方法,以及把控好它们存储的下标位置。

注意:在最开始定义数组时没有初始化的话,后面再初始化时就需要这样来初始化了就是先new再后面{}中进行赋值。

2.3.3 NormalUser类

与Administrator几乎一样,不一样的是接口类型变量中存入的方法,与打印的菜单内容不同。定义一个NormalUser类代表普通用户,作为子类继承父类User,继承后要帮助从父类继承来的变量进行构造初始化,在这里还有一个专属于普通用户的菜单。

成员变量:已经继承了父类User的成员变量,且无需有新的成员变量。因此只需要一个构造方法,帮助继承父类的成员变量进行初始化。

成员方法:

①创建构造方法,用来初始化从父类继承下来的成员变量。在用户选择管理员身份时,会new一个普通用户对象,此时便会自动给这个对象进行初始化。以便于后续调用这个对象中的一些变量和方法。

②创建menu方法,重写父类的menu菜单。并sout出普通用户的菜单,返回值类型为int类型,并return choice。便于后续在Main函数接收这个数值来调用不同的功能方法。因此父类中的抽象方法menu,也需要将返回值设置为int类型。

以下是NormalUser类中的所有代码:

package User;import Operation.*;
import java.util.Scanner;
public class NormalUser extends User{public NormalUser(String name) {super(name);this.iOperations =new IOperation[]{new ExitOperation(),new FindOperation(),new BorrowOperation(),new ReturnOperation(),};}@Overridepublic int menu() {System.out.println("***************************");System.out.println("hello! "+this.name+" 欢迎来到普通用户菜单");System.out.println("1.查找图书");System.out.println("2.借阅图书");System.out.println("3.归还图书");System.out.println("0.退出系统");System.out.println("***************************");System.out.println("请输入你的操作:");Scanner scanner = new Scanner(System.in);int choice = scanner.nextInt();return choice;}
}

本类是用户User类的一个子类,普通用户类,它的作用是使用户可以使用普通用户身份来运行这个程序。这样会实现不同的功能。

易错点:

1.由于父类有name的构造方法,因此在子类中也要有构造方法,对继承父类来的name变量进行构造。

2.用this.去引用父类中的接口类型数组iOperations。并对其初始化,输入你想实现的功能方法,以及把控好它们存储的下标位置。

注意:在最开始定义数组时没有初始化的话,后面再初始化时就需要这样来初始化了就是先new再后面{}中进行赋值。

2.2.4菜单功能选择的框架实现

在我们创建User时,创建了接口类型的变量。在管理员和普通用户中继承了这个变量,并分别对这个变量进行了各自的构造。各个功能的类被当作数组元素存入了这个数组,当我们想用到这个功能时,我们只需要在这个数组中传入对应的下标,再调用类中的方法就可以了。

当菜单建成,用户输入了1之后,接下来该怎么办呢?我们应该对这个菜单设置一个返回值(管理员和普通用户都需要将菜单的返回值改为int类型,并return choice),返回值类型为int,后续我们在主main中去接收这个值。

之后我们将这个数值用User中的doOperation方法当作下标传入我们之前定义的接口类型的数组当中。传入bookList这个书架的对象是因为在User.doOperation这个方法中有iOperations[choice].work(bookList);会调用对应的功能,在功能的实现里会用到bookList书架。

int choice = user.menu();

User.doOperation (choice,bookList);


Main类

到这里这个图书管理系统的大概框架就写好了,我们去Main方法中,试着让这个代码运行起来,为此我们还需要在Main类中创建以下内容。

1.登录,第一步我们我进行登录,在Main类中创建一个login方法,输入你的姓名。之后输入你的身份。之后确认了姓名与身份,我们就要实例化一个管理员对象或者普通用户对象,并返回这个对象。这个登录方法的返回值类型我们可以设置成User类型,这就用到了向上转型,将子类向上转型为父类。再用父类调用menu这个方法,多态就实现了。

2.创建main方法。

①首先我们实例化书架这个对象,BookList bookList = new BookList();并且调用了构造方法,此时书架上就有了我们初始化的三本书。

②用父类User接收这个管理员或者普通用户对象User user = login();这样就实现了向上转型,将子类的对象传给父类。由于我们父类也有menu这个方法,并与子类形成了方法的重写。因此我们才可以用父类对象去调用menu这个方法,才能实现多态。如果父类没有menu方法,没有形成重写,父类是不可以调用子类的方法的。

3.由于不同用户看到的菜单不同。我们用以下代码来实现我们想要达到的操作。这就是上一点讲到的多态的实现。不过多了个我们将这个menu方法的返回值传给了整型choice这个变量。这就是在接收管理员类和普通用户类中menu方法的返回值。

int choice = user.menu();

通过user和choice我们可以确定此时是哪个用户的哪个方法。此时我们给这两句代码加上循环。这样就可以实现让用户使用完一个功能后继续在选择其他功能,而不是程序停止运行。

while(ture){

       int choice = user.menu();
       user.doOperation(choice,bookList);

}

以下是我们Main类中的所有代码

import Operation.IOperation;
import User.User;
import java.util.Scanner;
import User.NormalUser;
import User.Administrator;
import book.BookList;public class Main {public static User login(){//可以利用返回值的向上转型,达到返回值的一致性System.out.println("请输入你的姓名:");Scanner scanner = new Scanner(System.in);String name = scanner.nextLine();System.out.println("请输入你的身份:1->管理员 0->普通用户");while (true){int choice = scanner.nextInt();if(choice == 1){return new Administrator(name);}else if (choice == 0){return new NormalUser(name);}else System.out.println("请重新输入:");}}public static void main(String[] args) {BookList bookList = new BookList();User user = login();while (true){int choice = user.menu();user.doOperation(choice,bookList);}}
}

程序从main中,开始运行, main中我们编写的代码很少,但是其中的逻辑是复杂的。

1.首先我们创建了一个书架类型的变量bookList,用它去接收了我们新建的对象new BookList。此时就有了我们在BookList类中定义的所有成员变量和方法都可以通过这个变量boookList来使用。

2.之后我们调用了login()方法。定义了User类型的变量user,用来接收login()这个方法的返回值可能是管理员也可能是普通用户。

3.此时实现了向上转型。再用user.menu()这个方法在User里面并且被子类继承,形成了方法的重写。就可以实现不同身份,看到不同的菜单。

4.user.doOperation(choice,bookList);方法用于我们传入数字,来实现不同的功能。加上while循环就可以在实现完一个功能后继续选择另一个功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/380814.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端基础之JavaScript学习——函数的使用

大家好我是来自CSDN的前端寄术区博主PleaSure乐事&#xff0c;今天我们继续有关JavaScript的学习&#xff0c;使用的编译器为vscode&#xff0c;浏览器为谷歌浏览器。 函数的声明与使用 声明 在JavaScript当中函数的声明和其他语言类似&#xff0c;使用如下格式即可声明&…

语义分割——为什么单通道8bit灰度图像能显示多种色块???

目录 一、问题二、解答2.1 标签图的实际存储格式2.2 标签图的显示颜色2.3 颜色映射示例 三、应用颜色映射3.1 OpenCV显示标签图3.2 Matplotlib显示标签图 四、总结 一、问题 大家在做语义分割时不知道有没有这样的疑惑&#xff0c;使用打标签工具后&#xff0c;标签图是单通道…

基于Python+Django,开发的一个在线教育系统

一、项目简介 使用Python的web框架Django进行开发的一个在线教育系统&#xff01; 二、所需要的环境与组件 Python3.6 Django1.11.7 Pymysql Mysql pure_pagination DjangoUeditor captcha xadmin crispy_forms 三、安装 1. 下载项目后进入项目目录cd Online-educ…

Bubbliiiing 的 Retinaface rknn python推理分析

Bubbliiiing 的 Retinaface rknn python推理分析 项目说明 使用的是Bubbliiiing的深度学习教程-Pytorch 搭建自己的Retinaface人脸检测平台的模型&#xff0c;下面是项目的Bubbliiiing视频讲解地址以及源码地址和博客地址&#xff1b; 作者的项目讲解视频&#xff1a;https:…

【网络安全科普】勒索病毒 防护指南

勒索病毒简介 勒索病毒是一种恶意软件&#xff0c;也称为勒索软件&#xff08;Ransomware&#xff09;&#xff0c;其主要目的是在感染计算机后加密用户文件&#xff0c;并要求用户支付赎金以获取解密密钥。这种类型的恶意软件通常通过电子邮件附件、恶意链接、下载的软件或漏洞…

基于重要抽样的主动学习不平衡分类方法ALIS

这篇论文讨论了数据分布不平衡对分类器性能造成的影响,并提出了一种新的有效解决方案 - 主动学习框架ALIS。 1、数据分布不平衡会影响分类器的学习性能。现有的方法主要集中在过采样少数类或欠采样多数类,但往往只采用单一的采样技术,无法有效解决严重的类别不平衡问题。 2、论…

Fast-Retry 高性能百万级任务重试框架介绍及使用

一、Fast-Retry 在本专栏的前面文章中我们介绍了 Spring 家族的 重试框架&#xff0c;本篇文章再给大家介绍一个高性能百万级任务重试框架 Fast-Retry 。它是一个高性能任务重试框架&#xff0c;可以支持百万级别任务的并发重试处理。与 Spring-Retry 不同&#xff0c;Fast-Re…

【JavaEE进阶】——Spring事务和事务传播机制

目录 &#x1f6a9;事务 &#x1f388;为什么需要事务? &#x1f388;事务的操作 &#x1f6a9;Spring 中事务的实现 &#x1f388;数据准备 &#x1f388;Spring 编程式事务(了解) &#x1f388;Spring 声明式事务 Transactional &#x1f36d;Transactional 详解 &…

阵列信号处理学习笔记(二)--空域滤波基本原理

阵列信号 阵列信号处理学习笔记&#xff08;一&#xff09;–阵列信号处理定义 阵列信号处理学习笔记&#xff08;二&#xff09;–空域滤波基本原理 文章目录 阵列信号前言一、阵列信号模型1.1 信号的基本模型1.2 阵列的几何构型1.3 均匀直线阵的阵列信号基本模型 总结 前言…

服务攻防-框架安全(漏洞复现)

关闭靶场 sudo docker-compose down 运行此靶场 sudo docker-compose up -d 查看启动环境 sudo docker ps 运行dockers容器 docker exec -it 64052abd288b /bin/bash thinkphp框架 thinkphp 2 - rce漏洞复现 docker exec -it 731dbae0e0b5 /bin/bash 集成化工具扫描 可以命令…

初学 Linux 必知必会的 X 个知识点

文章目录 一、Linux 系统与 Windows 系统的差别二、Linux 命令行初识1. 终端界面2. 路径的含义3. 命令结构说明4. 常见的 Linux 命令4-1. 文件和目录操作4-2. 网络相关命令 5. 使用命令行时的小技巧5-1. 使用 TAB 键补全5-2. 巧用通配符 *5-3. 命令行历史功能 三、文件的详细信…

linux在ssh的时候询问,yes or no 如何关闭

解决&#xff1a; 在~/.ssh/config文件中添加如下配置项&#xff1a; Host *StrictHostKeyChecking no

深度洞见|探索与突破:大模型在中国市场的实践

1 大模型产业应用的发展趋势 // 人工智能产业进入高速发展期&#xff0c;创造多个技术、市场、监管的里程碑 自2022年ChatGPT问世后&#xff0c;生成式AI&#xff08;大模型&#xff09;进入高速发展期&#xff0c;标志着AI经济新纪元的到来。大模型技术的快速迭代不仅促进了…

python—爬虫爬取电影页面实例

下面是一个简单的爬虫实例&#xff0c;使用Python的requests库来发送HTTP请求&#xff0c;并使用lxml库来解析HTML页面内容。这个爬虫的目标是抓取一个电影网站&#xff0c;并提取每部电影的主义部分。 首先&#xff0c;确保你已经安装了requests和lxml库。如果没有安装&#x…

一、C#概述

本文是网页版《C# 12.0 本质论》第一章解读。欲完整跟踪本系列文章&#xff0c;请关注并订阅我的Essential C# 12.0解读专栏。 前言 第一章的内容非常简单&#xff0c;毕竟仅仅是Introducing C#。不过正如《0.前言》所述&#xff0c;《C# 12.0本质论》本身就不是一本零基础的…

【Python游戏】编程开发贪吃蛇游戏(第一期)

本文收录于 《一起学Python趣味编程》专栏&#xff0c;从零基础开始&#xff0c;分享一些Python编程知识&#xff0c;欢迎关注&#xff0c;谢谢&#xff01; 文章目录 一、前言二、贪吃蛇游戏开发简介2.1 贪吃蛇游戏规则2.2 贪吃蛇游戏开发步骤 三、贪吃蛇游戏开发实战四、总结…

多任务高斯过程数学原理和Pytorch实现示例

高斯过程其在回归任务中的应用我们都很熟悉了&#xff0c;但是我们一般介绍的都是针对单个任务的&#xff0c;也就是单个输出。本文我们将讨论扩展到多任务gp&#xff0c;强调它们的好处和实际实现。 本文将介绍如何通过共区域化的内在模型(ICM)和共区域化的线性模型(LMC)&…

【开源库】libodb库编译及使用

前言 本文介绍windows平台下libodb库的编译及使用。 文末提供libodb-2.4.0编译好的msvc2019_64版本&#xff0c;可直接跳转自取 ODB库学习相关 【开源库学习】libodb库学习&#xff08;一&#xff09; 【开源库学习】libodb库学习&#xff08;二&#xff09; 【开源库学习】…

数据库之存储引擎

目录 一、MySQL支持的存储引擎 二、查看MySQL默认存储引擎 三、修改MySQL默认存储引擎 四、常用的存储引擎 1.InnoDB 2.MyISAM 3.MEMORY 一、MySQL支持的存储引擎 使用SHOW ENGINES \G; 命令查看 以“\G”结尾&#xff0c;其作用是将查询结果按列显示。 Engine&#xff…

人工智能与语音识别:技术进步与应用前景

引言 人工智能&#xff08;AI&#xff09;作为当今科技进步的核心驱动力&#xff0c;正在各个领域展现其变革力量。其中&#xff0c;语音识别技术作为人工智能的重要应用之一&#xff0c;已经深入到我们的日常生活和工作中。从智能助手如Siri、Google Assistant&#xff0c;到智…