java面向对象多态综合练习示例


以下是一个综合练习的 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 和三个子类 SedanSUVTruck。每个子类都重写了基类中的 displayInfo 方法,以便根据车型输出不同的属性信息。在测试代码中,我们创建了三个不同类型的汽车对象,并使用多态性调用每种汽车的 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 类作为所有图书的基类,该类包含图书的一些基本属性和方法,例如图书的名称、作者、价格和借阅状态等:

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 方法来获取图书的属性值。此外,我们还定义了 borrowreturnBook 方法来处理借阅和归还图书的操作。这两个方法中,我们使用了 isBorrowed 属性来记录图书的借阅状态。

另外,我们将 displayInfo 方法定义为抽象方法。因为不同类型的图书具有不同的属性,例如期刊和报纸可能有期数和日期等属性,而普通书籍则没有。因此,我们将 displayInfo 方法定义为抽象方法,并在每个具体的子类中实现该方法。

接下来,我们定义三个具体的子类来表示不同类型的图书,分别是 Book 类的子类 JournalNewspaperRegularBook

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 类没有任何特有属性。

每个子类中都实现了 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 类型的引用来引用它们。然后,我们可以调用 borrowdisplayInforeturnBook 方法来处理图书的借阅、展示和归还操作。这里使用的是多态性,因为不同类型的图书实际上是由不同的子类实现的,但是我们使用了基类 Book 类型的引用来引用它们,并调用了基类 Book 类中的通用方法。

接下来,我们来完善一下这个图书馆管理系统。假设图书馆有一个存储所有图书的数组,我们可以在数组中存储不同类型的图书,并且可以实现借阅、还书和查找图书的功能。

首先,我们可以在 Library 类中定义一个 books 数组来存储所有图书:

public class Library {
    private Book[] books;

    public Library(int capacity) {
        books = new Book[capacity];
    }

    // Other methods go here
}

在构造方法中,我们传入了一个整数参数 capacity,用于指定图书馆能够存储的最大图书数量。然后,我们在构造方法中创建了一个 books 数组,并初始化数组大小为 capacity

接下来,我们需要实现向图书馆中添加图书的功能。我们可以定义一个 addBook 方法,将新的图书对象添加到 books 数组中。由于 books 数组中存储的是基类 Book 类型的对象,我们可以使用多态性来实现添加不同类型的图书:

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 方法来查找图书是否存在于图书馆中:

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

borrowBook 方法中,我们调用了 findBook 方法来查找指定标题的图书,然后检查该图书是否已被借出。如果该图书存在且未被借出,则将该图书标记为已借出,并返回 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。然后,我们创建了两本图书 book1book2,并将它们添加到图书馆中。接着,我们借阅了两本图书,并将 Java编程思想 这本书归还了图书馆。最后,我们检查 book1book2 的借阅状态,并输出了它们的状态。

这就是一个简单的基于多态的图书馆管理系统的实现。通过这个例子,我们可以看到多态性在实际编程中的应用。多态性可以帮助我们更好地实现面向对象的程序设计,提高程序的灵活性、可扩展性和可维护性。在实际开发中,我们可以使用多态来实现各种设计模式,如工厂模式、单例模式、装饰器模式、观察者模式等。

另外,需要注意的是,虽然多态性可以提高程序的灵活性和可扩展性,但也会增加程序的复杂度和运行时开销。因此,在实际开发中,我们应该根据具体情况权衡利弊,适量地使用多态性。

最后,多态性是面向对象编程中一个非常重要的概念,也是Java语言中的一个核心特性。对于Java程序员来说,掌握多态性的原理和应用是必不可少的。

好的,那我们再来看一个多态性的示例。

假设我们有一个 Shape 类,它表示一个几何图形,具有计算面积和周长的功能:

public abstract class Shape {
    public abstract double getArea();
    public abstract double getPerimeter();
}

Shape 类是一个抽象类,其中包含两个抽象方法 getAreagetPerimeter,它们分别用于计算几何图形的面积和周长。由于不同类型的几何图形计算面积和周长的方法不同,因此这两个方法被声明为抽象方法,由子类来实现。

接下来,我们可以创建一些具体的几何图形,如圆形、矩形和三角形。这些具体的几何图形都是 Shape 类的子类,它们分别实现了 getAreagetPerimeter 方法:

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;
    }
}

这些具体的几何图形都重写了 getAreagetPerimeter 方法,以计算各自的面积和周长。例如,圆形的面积计算公式为 πr²,周长计算公式为 2πr,所以在 Circle 类中重写了这两个方法。类似地,矩形和三角形也分别实现了这两个方法。

现在,我们可以在一个程序中使用这些几何图形,并调用它们的 getAreagetPerimeter 方法。由于它们都是 Shape 类的子类,所以我们可以定义一个数组来存储这些几何图形,以便更方便地进行处理:

public static void main(String[] args) {
    Shape[] shapes = new Shape[3];
    shapes[0] = new Circle(2.0);
    shapes[

现在,我们可以在一个程序中使用这些几何图形,并调用它们的 getAreagetPerimeter 方法。由于它们都是 Shape 类的子类,所以我们可以定义一个数组来存储这些几何图形,以便更方便地进行处理:

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,并使用不同的具体几何图形对象初始化了数组的元素。然后,我们使用一个循环遍历数组,并分别调用每个元素的 getAreagetPerimeter 方法,输出每个几何图形的面积和周长。

由于 CircleRectangleTriangle 类都是 Shape 类的子类,它们都重写了 getAreagetPerimeter 方法。因此,当我们调用 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 类型的数组,调用不同类型的几何图形的 getAreagetPerimeter 方法,实现了代码的简洁和灵活性。


原文链接:codingdict.net