以下是一个综合练习的 Java 多态示例,假设有一个汽车销售系统,包括三种类型的汽车:轿车、越野车和卡车。每种汽车都有不同的属性和方法,但它们都可以调用汽车基类中的方法。这里的练习是实现一个汽车销售系统,其中要求使用多态性来创建汽车对象,并且能够根据汽车类型自动调用适当的方法。
// 定义汽车基类 class Car { private String brand; private String color; private int price; public Car(String brand, String color, int price) { this.brand = brand; this.color = color; this.price = price; } public void displayInfo() { System.out.println("品牌:" + brand); System.out.println("颜色:" + color); System.out.println("价格:" + price); } } // 定义轿车子类 class Sedan extends Car { private int numSeats; public Sedan(String brand, String color, int price, int numSeats) { super(brand, color, price); this.numSeats = numSeats; } public void displayInfo() { super.displayInfo(); System.out.println("座位数:" + numSeats); } } // 定义越野车子类 class SUV extends Car { private int numDoors; public SUV(String brand, String color, int price, int numDoors) { super(brand, color, price); this.numDoors = numDoors; } public void displayInfo() { super.displayInfo(); System.out.println("门数:" + numDoors); } } // 定义卡车子类 class Truck extends Car { private int payload; public Truck(String brand, String color, int price, int payload) { super(brand, color, price); this.payload = payload; } public void displayInfo() { super.displayInfo(); System.out.println("载重:" + payload + "吨"); } } // 测试代码 public class CarSalesSystem { public static void main(String[] args) { // 创建多个不同类型的汽车 Car car1 = new Sedan("Toyota", "Red", 250000, 5); Car car2 = new SUV("Jeep", "Blue", 350000, 4); Car car3 = new Truck("Volvo", "Green", 500000, 10); // 使用多态性调用每种汽车的 displayInfo 方法 car1.displayInfo(); car2.displayInfo(); car3.displayInfo(); } }
在上面的示例中,我们定义了一个汽车基类 Car 和三个子类 Sedan、SUV 和 Truck。每个子类都重写了基类中的 displayInfo 方法,以便根据车型输出不同的属性信息。在测试代码中,我们创建了三个不同类型的汽车对象,并使用多态性调用每种汽车的 displayInfo 方法。这样,我们就可以根据汽车类型自动调用适当
Car
Sedan
SUV
Truck
displayInfo
的方法,而不需要手动判断每个汽车的类型。
另外,我们还可以通过将不同类型的汽车对象存储在同一个数组中,来进一步利用多态性。以下是示例代码:
public class CarSalesSystem { public static void main(String[] args) { // 创建不同类型的汽车 Car car1 = new Sedan("Toyota", "Red", 250000, 5); Car car2 = new SUV("Jeep", "Blue", 350000, 4); Car car3 = new Truck("Volvo", "Green", 500000, 10); // 将汽车对象存储在同一个数组中 Car[] cars = {car1, car2, car3}; // 使用循环和多态性调用每种汽车的 displayInfo 方法 for (Car car : cars) { car.displayInfo(); } } }
在上面的代码中,我们创建了三个不同类型的汽车对象,并将它们存储在一个 Car 类型的数组中。然后,我们使用循环和多态性调用每种汽车的 displayInfo 方法,以便输出每个汽车的属性信息。这样,我们就可以使用一个循环来处理多个汽车对象,而不需要针对每个对象编写重复的代码。
总之,多态性是面向对象编程中一个非常重要的概念,可以帮助我们编写更加灵活和可扩展的代码。通过使用多态性,我们可以将不同类型的对象视为同一类型的对象,从而实现更加通用和简洁的代码。
下面是一个更加实际的示例,假设我们正在开发一个图书馆管理系统,其中有三种类型的图书:普通书籍、期刊和报纸。我们可以通过多态性来处理不同类型的图书,并实现一些通用的功能,例如借出图书、归还图书、查询图书等。
首先,我们定义一个 Book 类作为所有图书的基类,该类包含图书的一些基本属性和方法,例如图书的名称、作者、价格和借阅状态等:
Book
public abstract class Book { protected String title; protected String author; protected double price; protected boolean isBorrowed; public Book(String title, String author, double price) { this.title = title; this.author = author; this.price = price; this.isBorrowed = false; } public String getTitle() { return title; } public String getAuthor() { return author; } public double getPrice() { return price; } public boolean isBorrowed() { return isBorrowed; } public void borrow() { if (!isBorrowed) { isBorrowed = true; System.out.println(title + " has been borrowed."); } else { System.out.println(title + " has already been borrowed."); } } public void returnBook() { if (isBorrowed) { isBorrowed = false; System.out.println(title + " has been returned."); } else { System.out.println(title + " has not been borrowed."); } } public abstract void displayInfo(); }
在 Book 类中,我们定义了一个构造方法来初始化图书的属性,以及一些公共的 getter 方法来获取图书的属性值。此外,我们还定义了 borrow 和 returnBook 方法来处理借阅和归还图书的操作。这两个方法中,我们使用了 isBorrowed 属性来记录图书的借阅状态。
borrow
returnBook
isBorrowed
另外,我们将 displayInfo 方法定义为抽象方法。因为不同类型的图书具有不同的属性,例如期刊和报纸可能有期数和日期等属性,而普通书籍则没有。因此,我们将 displayInfo 方法定义为抽象方法,并在每个具体的子类中实现该方法。
接下来,我们定义三个具体的子类来表示不同类型的图书,分别是 Book 类的子类 Journal、Newspaper 和 RegularBook:
Journal
Newspaper
RegularBook
public class Journal extends Book { private int issueNumber; private String date; public Journal(String title, String author, double price, int issueNumber, String date) { super(title, author, price); this.issueNumber = issueNumber; this.date = date; } public int getIssueNumber() { return issueNumber; } public String getDate() { return date; } public void displayInfo() { System.out.println("Journal - " + title); System.out.println("Author: " + author); System.out.println("Price: " + price); System.out.println("Issue Number: "
" + issueNumber); System.out.println("Date: " + date); } } public class Newspaper extends Book { private String date; public Newspaper(String title, String author, double price, String date) { super(title, author, price); this.date = date; } public String getDate() { return date; } public void displayInfo() { System.out.println("Newspaper - " + title); System.out.println("Author: " + author); System.out.println("Price: " + price); System.out.println("Date: " + date); } } public class RegularBook extends Book { public RegularBook(String title, String author, double price) { super(title, author, price); } public void displayInfo() { System.out.println("Regular Book - " + title); System.out.println("Author: " + author); System.out.println("Price: " + price); } }
在每个子类中,我们使用 super 关键字调用基类的构造方法来初始化基类的属性。此外,我们还定义了子类特有的属性和方法,例如 Journal 类有期数和日期属性,Newspaper 类有日期属性,而 RegularBook 类没有任何特有属性。
super
每个子类中都实现了 displayInfo 方法,该方法根据图书类型不同来输出不同的信息。例如,Journal 类中的 displayInfo 方法输出了期刊的期数和日期信息,而 RegularBook 类中的 displayInfo 方法只输出了书籍的基本信息。
最后,我们可以使用多态性来处理不同类型的图书,例如:
public class Library { public static void main(String[] args) { Book book1 = new Journal("Scientific American", "Various", 9.99, 123, "2022-05-01"); Book book2 = new Newspaper("New York Times", "Various", 3.99, "2022-05-05"); Book book3 = new RegularBook("To Kill a Mockingbird", "Harper Lee", 12.99); book1.borrow(); book2.borrow(); book3.borrow(); book1.displayInfo(); book2.displayInfo(); book3.displayInfo(); book1.returnBook(); book2.returnBook(); book3.returnBook(); } }
在 Library 类中,我们创建了三个不同类型的图书对象,并使用基类 Book 类型的引用来引用它们。然后,我们可以调用 borrow、displayInfo 和 returnBook 方法来处理图书的借阅、展示和归还操作。这里使用的是多态性,因为不同类型的图书实际上是由不同的子类实现的,但是我们使用了基类 Book 类型的引用来引用它们,并调用了基类 Book 类中的通用方法。
Library
接下来,我们来完善一下这个图书馆管理系统。假设图书馆有一个存储所有图书的数组,我们可以在数组中存储不同类型的图书,并且可以实现借阅、还书和查找图书的功能。
首先,我们可以在 Library 类中定义一个 books 数组来存储所有图书:
books
public class Library { private Book[] books; public Library(int capacity) { books = new Book[capacity]; } // Other methods go here }
在构造方法中,我们传入了一个整数参数 capacity,用于指定图书馆能够存储的最大图书数量。然后,我们在构造方法中创建了一个 books 数组,并初始化数组大小为 capacity。
capacity
接下来,我们需要实现向图书馆中添加图书的功能。我们可以定义一个 addBook 方法,将新的图书对象添加到 books 数组中。由于 books 数组中存储的是基类 Book 类型的对象,我们可以使用多态性来实现添加不同类型的图书:
addBook
public void addBook(Book book) { for (int i = 0; i < books.length; i++) { if (books[i] == null) { books[i] = book; break; } } }
在 addBook 方法中,我们遍历了整个 books 数组,查找第一个空的位置,并将新的图书对象添加到该位置。如果数组已满,则不会添加新的图书。
接下来,我们可以实现借阅图书的功能。我们可以定义一个 borrowBook 方法,遍历 books 数组,找到匹配的图书,并将该图书标记为已借出。我们还可以实现一个 findBook 方法来查找图书是否存在于图书馆中:
borrowBook
findBook
public Book findBook(String title) { for (int i = 0; i < books.length; i++) { if (books[i] != null && books[i].getTitle().equals(title)) { return books[i]; } } return null; } public boolean borrowBook(String title) { Book book = findBook(title); if (book != null && !book.isBorrowed()) { book.borrow(); return true; } return false; }
在 findBook 方法中,我们遍历了整个 books 数组,查找指定标题的图书。如果找到了匹配的图书,则返回该图书对象,否则返回 null。
null
在 borrowBook 方法中,我们调用了 findBook 方法来查找指定标题的图书,然后检查该图书是否已被借出。如果该图书存在且未被借出,则将该图书标记为已借出,并返回 true,否则返回 false。
true
false
最后,我们可以实现还书的功能。我们可以定义一个 returnBook 方法,遍历 books 数组,找到匹配的图书,并将该图书标
记为未借出。我们同样可以调用 findBook 方法来查找指定标题的图书:
public boolean returnBook(String title) { Book book = findBook(title); if (book != null && book.isBorrowed()) { book.returnBook(); return true; } return false; }
在 returnBook 方法中,我们调用了 findBook 方法来查找指定标题的图书,然后检查该图书是否已被借出。如果该图书存在且已被借出,则将该图书标记为未借出,并返回 true,否则返回 false。
下面是完整的 Library 类代码:
public class Library { private Book[] books; public Library(int capacity) { books = new Book[capacity]; } public void addBook(Book book) { for (int i = 0; i < books.length; i++) { if (books[i] == null) { books[i] = book; break; } } } public Book findBook(String title) { for (int i = 0; i < books.length; i++) { if (books[i] != null && books[i].getTitle().equals(title)) { return books[i]; } } return null; } public boolean borrowBook(String title) { Book book = findBook(title); if (book != null && !book.isBorrowed()) { book.borrow(); return true; } return false; } public boolean returnBook(String title) { Book book = findBook(title); if (book != null && book.isBorrowed()) { book.returnBook(); return true; } return false; } }
使用这个图书馆管理系统的示例代码:
public static void main(String[] args) { Library library = new Library(10); Book book1 = new Book("Java编程思想", "Bruce Eckel"); Book book2 = new AudioBook("哈利波特与魔法石", "J.K. Rowling", "Jim Dale"); library.addBook(book1); library.addBook(book2); library.borrowBook("Java编程思想"); library.borrowBook("哈利波特与魔法石"); library.returnBook("Java编程思想"); System.out.println(book1.isBorrowed()); // 输出 false System.out.println(book2.isBorrowed()); // 输出 true }
在这个示例代码中,我们创建了一个 Library 对象,指定其最大容量为 10。然后,我们创建了两本图书 book1 和 book2,并将它们添加到图书馆中。接着,我们借阅了两本图书,并将 Java编程思想 这本书归还了图书馆。最后,我们检查 book1 和 book2 的借阅状态,并输出了它们的状态。
book1
book2
Java编程思想
这就是一个简单的基于多态的图书馆管理系统的实现。通过这个例子,我们可以看到多态性在实际编程中的应用。多态性可以帮助我们更好地实现面向对象的程序设计,提高程序的灵活性、可扩展性和可维护性。在实际开发中,我们可以使用多态来实现各种设计模式,如工厂模式、单例模式、装饰器模式、观察者模式等。
另外,需要注意的是,虽然多态性可以提高程序的灵活性和可扩展性,但也会增加程序的复杂度和运行时开销。因此,在实际开发中,我们应该根据具体情况权衡利弊,适量地使用多态性。
最后,多态性是面向对象编程中一个非常重要的概念,也是Java语言中的一个核心特性。对于Java程序员来说,掌握多态性的原理和应用是必不可少的。
好的,那我们再来看一个多态性的示例。
假设我们有一个 Shape 类,它表示一个几何图形,具有计算面积和周长的功能:
Shape
public abstract class Shape { public abstract double getArea(); public abstract double getPerimeter(); }
Shape 类是一个抽象类,其中包含两个抽象方法 getArea 和 getPerimeter,它们分别用于计算几何图形的面积和周长。由于不同类型的几何图形计算面积和周长的方法不同,因此这两个方法被声明为抽象方法,由子类来实现。
getArea
getPerimeter
接下来,我们可以创建一些具体的几何图形,如圆形、矩形和三角形。这些具体的几何图形都是 Shape 类的子类,它们分别实现了 getArea 和 getPerimeter 方法:
public class Circle extends Shape { private double radius; public Circle(double radius) { this.radius = radius; } @Override public double getArea() { return Math.PI * radius * radius; } @Override public double getPerimeter() { return 2 * Math.PI * radius; } } public class Rectangle extends Shape { private double width; private double height; public Rectangle(double width, double height) { this.width = width; this.height = height; } @Override public double getArea() { return width * height; } @Override public double getPerimeter() { return 2 * (width + height); } } public class Triangle extends Shape { private double a; private double b; private double c; public Triangle(double a, double b, double c) { this.a = a; this.b = b; this.c = c; } @Override public double getArea() { double p = (a + b + c) / 2; return Math.sqrt(p * (p - a) * (p - b) * (p - c)); } @Override public double getPerimeter() { return a + b + c; } }
这些具体的几何图形都重写了 getArea 和 getPerimeter 方法,以计算各自的面积和周长。例如,圆形的面积计算公式为 πr²,周长计算公式为 2πr,所以在 Circle 类中重写了这两个方法。类似地,矩形和三角形也分别实现了这两个方法。
Circle
现在,我们可以在一个程序中使用这些几何图形,并调用它们的 getArea 和 getPerimeter 方法。由于它们都是 Shape 类的子类,所以我们可以定义一个数组来存储这些几何图形,以便更方便地进行处理:
public static void main(String[] args) { Shape[] shapes = new Shape[3]; shapes[0] = new Circle(2.0); shapes[
public static void main(String[] args) { Shape[] shapes = new Shape[3]; shapes[0] = new Circle(2.0); shapes[1] = new Rectangle(3.0, 4.0); shapes[2] = new Triangle(3.0, 4.0, 5.0); for (int i = 0; i < shapes.length; i++) { System.out.println("Shape " + i + ":"); System.out.println("Area = " + shapes[i].getArea()); System.out.println("Perimeter = " + shapes[i].getPerimeter()); System.out.println(); } }
在这个程序中,我们创建了一个 Shape 类型的数组 shapes,并使用不同的具体几何图形对象初始化了数组的元素。然后,我们使用一个循环遍历数组,并分别调用每个元素的 getArea 和 getPerimeter 方法,输出每个几何图形的面积和周长。
shapes
由于 Circle、Rectangle 和 Triangle 类都是 Shape 类的子类,它们都重写了 getArea 和 getPerimeter 方法。因此,当我们调用 shapes[i].getArea() 和 shapes[i].getPerimeter() 时,实际上会根据当前元素的实际类型,调用相应的重写方法。这就体现了多态性的特点,即同一个方法在不同的对象上执行时,会根据对象的实际类型调用相应的方法。
Rectangle
Triangle
shapes[i].getArea()
shapes[i].getPerimeter()
输出结果如下:
Shape 0: Area = 12.566370614359172 Perimeter = 12.566370614359172 Shape 1: Area = 12.0 Perimeter = 14.0 Shape 2: Area = 6.0 Perimeter = 12.0
从输出结果中可以看出,程序正确地计算出了每个几何图形的面积和周长,并输出了相应的结果。同时,我们也看到了多态性的应用,即使用同一个 Shape 类型的数组,调用不同类型的几何图形的 getArea 和 getPerimeter 方法,实现了代码的简洁和灵活性。
原文链接:codingdict.net