多态

多态的基本使用

实体类

package Person;

/**
* @author sakurasep
* * @date 2024/3/13
**/
public class Person {
String name;
int age;
public void eat(){
System.out.println("人吃饭");
}

public void walk(){
System.out.println("人走路");
}

}

package Person;

/**
* @author sakurasep
* * @date 2024/3/13
**/
public class Man extends Person{
boolean isSomking;

public void eat(){
System.out.println("男人吃肉");
}

public void walk(){
System.out.println("男人走路");
}

public void play(){
System.out.println("男人打游戏");
}
}

package Person;

/**
* @author sakurasep
* * @date 2024/3/13
**/
public class Woman extends Person{
boolean isBeauty;
public void eat(){
System.out.println("女人吃甜点");
}

public void walk(){
System.out.println("女人走路");
}

public void watch(){
System.out.println("女人看剧");
}
}

package Person;

/**
* @author sakurasep
* * @date 2024/3/13
**/
public class PersonTest {
public static void main(String[] args) {
Person person = new Person();
person.eat();
person.walk();

Man man = new Man();
man.eat();
man.walk();

Woman woman = new Woman();
woman.eat();
woman.walk();

System.out.println("*********多态性********");

Person person1 = new Man();
person1.eat();
person1.walk();

Person person2 = new Woman();
person2.eat();
person2.walk();
}
}


测试方法

package Person;

/**
* @author sakurasep
* * @date 2024/3/13
**/
public class PersonTest {
public static void main(String[] args) {
Person person = new Person();
person.eat();
person.walk();

Man man = new Man();
man.eat();
man.walk();

Woman woman = new Woman();
woman.eat();
woman.walk();

System.out.println("*********多态性********");

Person person1 = new Man();
person1.eat();
person1.walk();

Person person2 = new Woman();
person2.eat();
person2.walk();

}

}

输出结果

image-20240313164918351

多态的实际使用

测试方法

源码

当不存在多态性的时候

package Person;

/**
* @author sakurasep
* * @date 2024/3/13
**/
public class AccountTest {
public static void main(String[] args) {
AccountTest test = new AccountTest();
test.console(new Account());
System.out.println("-------------");
test.console(new CheckAccount());
System.out.println("-------------");
test.console(new SaveAccount());
}
public void console(Account account){
account.saveMoney(100);
account.getMoney(40);
}

public void console(CheckAccount account){
account.saveMoney(100);
account.getMoney(40);
}

public void console(SaveAccount account){
account.saveMoney(100);
account.getMoney(40);
}

}
class Account {
String username;
String password;
int money; // 余额

// 存钱
public void saveMoney(int money) {
this.money = money;
System.out.printf("普通账户余额为: %d\n", this.money);
}

// 取钱
public void getMoney(int money) {
if(money <= this.money) {
this.money -= money;
System.out.printf("普通账户余额为: %d\n", this.money);
}
else {
System.out.println("普通账户余额不足");
}
}
}

class CheckAccount extends Account {
int quota = 500; // 额度
public void saveMoney(int money) {
this.money = money + quota;
System.out.printf("信用卡账户余额为: %d\n", this.money);
}

// 取钱
public void getMoney(int money)
{
if(this.money >= money) {
this.money -= money;
System.out.printf("信用卡余额为: %d\n", this.money);
}
else {
System.out.println("信用卡余额不足");
}
}

}

class SaveAccount extends Account {
float money;
float rate = 0.2F; // 利率
float interest; // 利息

public void saveMoney(int money) {
interest = money * rate;
this.money = money + interest;
System.out.printf("储蓄卡预期余额为: %f\n", this.money);
}

public void getMoney(int money) {
if(this.money - interest > money) {
this.money -= money;
System.out.printf("储蓄卡余额为: %f\n", this.money);
}
else {
System.out.println("储蓄卡余额不足");
}
}
}

正常情况下,如果没有 Java 的多态性,那么对于不同对象的方法调用,就需要如下这样写多个同名方法,赋予不同对象的形参

public void console(Account account){
account.saveMoney(100);
account.getMoney(40);
}

public void console(CheckAccount account){
account.saveMoney(100);
account.getMoney(40);
}

public void console(SaveAccount account){
account.saveMoney(100);
account.getMoney(40);
}

而因为 Java 的多态性,这里的方法便可以省略重复调用,在实际的项目中,多态很有用,符合开闭原则。对于增加新的子类,方法都不需要进行改变,只定义一个父类即可。

public void console(Account account){
account.saveMoney(100);
account.getMoney(40);
}

输出结果

image-20240319110110588

Java 向下转型

测试方法

虽然创建的子类的对象,也加载了子类的特有的方法和属性,但是因为我们声明的是父类的引用,所以没有办法直接调用子类特有的属性和方法。

注意,在向下转型的时候可能会出现类型转换异常,即你要转换的类型并不是你声明的类型

所以在进行向下转型之前,为了程序的健壮性,最好使用 instanceof 进行判断

public class AccountTest {
public static void main(String[] args) {
AccountTest test = new AccountTest();
test.console(new CheckAccount());
test.console(new SaveAccount());
}
public void console(Account account){
account.saveMoney(100);
account.getMoney(40);

// 避免出现类型转换异常
if (account instanceof CheckAccount){
CheckAccount check_account = (CheckAccount)account;
check_account.getQuota();
}

if (account instanceof SaveAccount){
SaveAccount save_account = (SaveAccount)account;
save_account.getInterest();
save_account.getRate();
}

}

}

输出结果

image-20240319143347946

多态案例练习

题目

image-20240319134006979

关系图

image-20240319134130028

实体类

package Geometric;

/**
* @author sakurasep
* * @date 2024/3/19
**/
public class GeometricObject {
protected String color;
protected double weight;

protected GeometricObject(String color, double weight) {
this.color = color;
this.weight = weight;
}

public String getColor() {
return color;
}

public void setColor(String color) {
this.color = color;
}

public double getWeight() {
return weight;
}

public void setWeight(double weight) {
this.weight = weight;
}

public double findArea(){
return 0;
}
}

package Geometric;

/**
* @author sakurasep
* * @date 2024/3/19
**/
public class Circle extends GeometricObject {
private double radius;

public Circle(String color, double weight, double radius) {
super(color, weight);
this.radius = radius;
}

public double getRadius() {
return radius;
}

public void setRadius(double radius) {
this.radius = radius;
}

@Override
public double findArea(){
return 3.14 * radius * radius;
}
}

package Geometric;

/**
* @author sakurasep
* * @date 2024/3/19
**/
public class MyRectangle extends GeometricObject{
private double width;
private double height;

public MyRectangle(String color, double weight, double width, double height) {
super(color, weight);
this.width = width;
this.height = height;
}

public double getWidth() {
return width;
}

public void setWidth(double width) {
this.width = width;
}

public double getHeight() {
return height;
}

public void setHeight(double height) {
this.height = height;
}

@Override
public double findArea() {
return width * height;
}
}

测试方法

package Geometric;

import Person.Man;

/**
* @author sakurasep
* * @date 2024/3/19
**/
public class GeometricTest {

public static void main(String[] args) {
GeometricTest test = new GeometricTest();
Circle c1 = new Circle("red", 1.0, 4);
Circle c2 = new Circle("bule", 1.0, 4);
MyRectangle m1 = new MyRectangle("red", 1.0, 4, 4);
test.displayGeometricObject(c1);
test.displayGeometricObject(c2);
test.displayGeometricObject(m1);

boolean isEquals = test.equalsArea(c1, c2);
if (isEquals){
System.out.println("面积相等");
}
else {
System.out.println("面积不等");
}

}
public boolean equalsArea(GeometricObject object1, GeometricObject object2){
return object1.findArea() == object2.findArea();
}

public void displayGeometricObject(GeometricObject object){
System.out.println("几何图形的面积为: " + object.findArea());
}
}

输出结果

image-20240319140928531

重写对象方法

重写 Object 类的 equals() 方法

对于 String,File ,包装类等已经重写了 Object 的 equals 方法。我们自己用的时候,通常也可以重写 equals 方法实现对象的应用。

当然 IDEA 自带重写 equals 方法

实体类

class User {
private int age;
private String name;

public User() {
}

public User(int age, String name) {
this.age = age;
this.name = name;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}

if (obj instanceof User) {
User user = (User) obj;
return this.age == user.age && this.name.equals(user.name);
}

return false;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

User user = (User) o;

if (age != user.age) return false;
return Objects.equals(name, user.name);
}
}

测试方法

public class UserTest {
public static void main(String[] args) {

User u1 = new User(10, "lihua");
User u2 = new User(10, "xiaoli");
User u3 = new User(10,"lihua");
System.out.println(u1.equals(u2));
System.out.println(u1.equals(u3));
}
}

输出结果

image-20240319155034611

重写 toString() 方法

和 equals 一样,String,File 等也已经预先重写了 toString 方法,对于自定义类,我们同样可以进行重写

@Override
public String toString() {
return "Use r" + "name: " + name + " age: " + age;
}

image-20240319183944770

当然,IDEA 也可以自动生成对象的 toString 方法

@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}

关键字 Static


关于我