19、对象多态性

本文深入探讨了Java中的多态性概念,包括方法重载、方法覆写以及对象的向上和向下转型。通过实例展示了多态性的应用,如参数统一和个性化操作,并讨论了转型的安全性和风险。

对象多态性

多态性依赖于方法覆写。

class A {
    public void print() {
        System.out.println("A中的方法");
    }
}

class B extends A {
    public void print() {
        System.out.println("覆写的方法");
    }
}

public class Demo {
    public static void main(String[] args) {
        B b = new B();
        b.print(); // 覆写的方法
    }
}

1、多态性分为两种:

(1)方法的多态性
	|- 方法重载:同一个方法名,根据传入的参数类型或个数的不同,执行不同方法体;
	|- 方法覆写:同一个方法,根据对象所属的子类不同,执行不同方法体。
(2)对象的多态性:指发生在具有继承关系的类中,父类与子类的转换。
	|- 向上转型(自动完成):父类 父类对象 = 子类实例化;
	|- 向下转型(强制完成):子类 子类对象 = (父类)父类实例化;

范例:向上转型

public class Demo {
    public static void main(String[] args) {
        A a = new B();
        a.print(); // 覆写的方法
    }
}

范例:向下转型

public class Demo {
    public static void main(String[] args) {
        B b = (B) new A(); // 向下转型
        b.print(); // 覆写的方法
    }
}

2、向上转型:由于子类对象都可以自动向上转型,所以可应用于参数的统一。

class A {
    public void print() {
        System.out.println("A中的方法");
    }
}

class B extends A {
    public void print() {
        System.out.println("B覆写的方法");
    }
}

class C extends A {
    public void print() {
        System.out.println("C覆写的方法");
    }
}

public class Demo {
    public static void main(String[] args) {
        A a1 = new B(); // 向上转型
        A a2 = new C(); // 向上转型
        a1.print(); // B覆写的方法
        a2.print(); // C覆写的方法
    }
}

a1,a2参数统一后,还可以调用子类覆写的方法,即同一个方法针对不同子类可以有不同实现。
3、向下转型:父类发生向上转型后,不能调用子类中自定义的方法。因此当父类要调用子类自定义方法时,需要进行向下转型,将父类对象变为子类对象。

class A {
}

class B extends A {
    public void fun() {
        System.out.println("自定义方法");
    }
}

public class Demo {
    public static void main(String[] args) {
        A a = new B(); // 向上转型
        a.fun(); // 报错,无法调用B自定义方法
    }
}

向下转型后,可以调用子类自定义的方法:

class A {
}

class B extends A {
    public void fun() {
        System.out.println("自定义方法");
    }
}

public class Demo {
    public static void main(String[] args) {
        A a = new B(); // 向上转型
        B b = (B) a; // 向下转型
        b.fun();
    }
}

问题:上述代码中不适用向下转型,直接实例化子类对象就可以直接调用fun(),为什么还要转型?
答:数据的操作分为两步:设置数据(最需要进行参数统一)和取出数据。

public class Demo {
    public static void main(String[] args) {
        fun(new B()); // 向上转型
    }
    public static void fun(A a){ // 统一参数
        B b = (B) a; // 向下转型
        b.fun(); // 调用子类自定义方法
    }
}

5、个性化操作在开发中尽量少出现,因为对象的强制转型容易带来安全隐患。

class A {
    public void print() {
        System.out.println("A.print()");
    }
}

class B extends A {
    public void print() {
        System.out.println("B.print()");
    }
}

public class Demo {
    public static void main(String[] args) {
        A a = new A();
        B b = (B) a;
        b.print();
    }
}

上述代码会报错,Exception in thread "main" java.lang.ClassCastException: A cannot be cast to B at ExDemo.main(ExDemo.java:15),表示类转换异常,指的是两个没有关系的类对象强制进行向下转型时发生的异常,因此向下转型存在风险。
为保证转型的安全性,Java提供关键字instanceof,其返回结果为boolean:对象 instanceof 类
如果某个对象是某个类的实例,则会返回true,反之返回false。

class A {
    public void print() {
        System.out.println("A.print()");
    }
}

class B extends A {
    public void print() {
        System.out.println("B.print()");
    }
}

public class Demo {
    public static void main(String[] args) {
        A a = new B();
        System.out.println(a instanceof A); // true
        System.out.println(a instanceof B); // true
        if (a instanceof B) {
            B b = (B) a;
            b.print(); // B.print()
        }
    }
}

向下转型前应先进行对象的向上转型,建立关系后才能进行向下转型。

总结:
(1)大多数情况只使用向上转型,使得参数统一,便于程序设计;子类尽量覆写方法,而不是自定义方法;
(2)极少情况使用向下转型调用子类的自定义方法,或者不转型。

### 面向对象程序设计(OOP)的核心概念 面向对象程序设计是一种编程范式,它将数据和对数据的操作封装在一个称为“对象”的实体中。这种设计方法强调了数据的封装性、继承性和多态性,使得程序更加模块化,易于维护和扩展。在面向对象的程序设计中,类是对象的模板,而对象则是类的具体实例。通过类,可以定义对象的数据成员(属性)和成员方法(行为)[^2]。 #### 类与对象 类是对一类具有相同特征和行为的对象的抽象描述。例如,所有“汽车”都可以被看作是一个类,它们具有共同的属性(如颜色、品牌、型号等)和行为(如启动、加速、刹车等)。而具体的某一辆汽车则是一个对象,它是类的一个实例。一个类可以创建多个对象,每个对象可以有不同的属性值,但共享相同的成员方法[^3]。 ```python class Car: def __init__(self, color, brand, model): self.color = color # 数据成员 self.brand = brand self.model = model def start(self): # 成员方法 print(f"{self.color} {self.brand} {self.model} is starting.") # 创建对象 car1 = Car("Red", "Toyota", "Corolla") car2 = Car("Blue", "Honda", "Civic") # 调用成员方法 car1.start() car2.start() ``` #### 封装 封装是面向对象程序设计的一个重要特性,它的是将对象的内部状态(数据成员)隐藏起来,只通过公共的方法(成员方法)与外界交互。这样做的好处是可以提高程序的安全性和可维护性。通常,类的成员属性会被定义为私有的(private),而成员方法则被定义为公有的(public),以确保外部只能通过预定的方式访问对象的状态[^4]。 ```python class BankAccount: def __init__(self, balance=0): self.__balance = balance # 私有数据成员 def deposit(self, amount): # 公共成员方法 if amount > 0: self.__balance += amount else: print("Deposit amount must be positive.") def withdraw(self, amount): if 0 < amount <= self.__balance: self.__balance -= amount else: print("Insufficient funds or invalid withdrawal amount.") def get_balance(self): return self.__balance # 使用封装的类 account = BankAccount(1000) account.deposit(500) account.withdraw(200) print(account.get_balance()) # 输出: 1300 ``` #### 继承 继承允许我们定义一个新类(子类),它可以继承另一个已存在的类(父类)的所有属性和方法。这有助于代码重用,并且可以建立类之间的层次关系。子类不仅可以使用父类的功能,还可以添加自己的新功能或覆盖父类的行为。 ```python class ElectricCar(Car): def __init__(self, color, brand, model, battery_capacity): super().__init__(color, brand, model) self.battery_capacity = battery_capacity def charge(self): print(f"Charging {self.color} {self.brand} {self.model} with {self.battery_capacity} kWh battery.") # 创建继承类的对象 electric_car = ElectricCar("Green", "Tesla", "Model S", 100) electric_car.start() electric_car.charge() ``` #### 多态 多态是同一个接口可以在不同的情况下表现出不同的行为。在面向对象的程序设计中,多态通常通过方法重写(覆盖)来实现。当一个子类提供了与父类同名的方法时,这个子类的方法就覆盖了父类的方法,从而实现了多态。 ```python class Animal: def sound(self): pass class Dog(Animal): def sound(self): print("Woof!") class Cat(Animal): def sound(self): print("Meow!") def make_sound(animal): animal.sound() # 多态示例 dog = Dog() cat = Cat() make_sound(dog) # 输出: Woof! make_sound(cat) # 输出: Meow! ``` ### 相关问题 1. 面向对象程序设计中的继承机制是如何工作的? 2. 如何在Python中实现多态? 3. 在面向对象程序设计中,封装的具体实现方式有哪些? 4. 面向对象程序设计中,类和对象之间的区别是什么? 5. 面向对象程序设计中的构造函数和析构函数的作用是什么? 希望这些内容能帮助您更好地理解和学习面向对象程序设计的相关知识。如果您有任何具体的问题或需要进一步的帮助,请随时告诉我!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会画画的画师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值