多态:父类引用指向子类对象。
C++在使用子类实例化父类对象时,如果不用抽象(virtual),那么无法实现多态性。
//不使用虚函数,即使重写,在Base* basePtr = new Derived()后,也无法体现多态性。
class Base {
public:
void nonVirtualFunction() {
cout << "Base: Non-virtual function" << endl;
}
};
class Derived : public Base {
public:
void nonVirtualFunction() {
cout << "Derived: Non-virtual function" << endl;
}
};
int main() {
Base* basePtr = new Derived();
basePtr->nonVirtualFunction(); // 输出结果:Base: Non-virtual function
return 0;
}
如果在父类中声明virtual nonVirtualFunction()且在子类重写后,输出才是Derived: Non-virtual function。
Java中,无论有无virtual 方法都是体现多态,子类的同名函数会override父类的(除非不重写,依旧是父类函数)。Java多态 可以理解为对子类使用的场景进行约束,即只可以使用父类声明过的方法(除非强制转型或在子类中声明一个新方法调用super接口,否则无法使用父类中的方法)。
//对使用场景进行约束的例子
//只能使用父类声明过的方法
//输出为This is parent's method. 因为子类没有重写。
//若子类重写parentMethod方法,即便没有virtual,依旧输出子类的结果 与C++不同。
class Parent {
void parentMethod() {
System.out.println("This is parent's method.");
}
}
class Child extends Parent {
void childMethod() {
System.out.println("This is child's method.");
}
}
public class Main {
public static void main(String[] args) {
Parent parentReference = new Child(); // 父类引用指向子类对象
parentReference.parentMethod(); // 调用父类方法
// parentReference.childMethod(); // 这行代码将引发编译错误,因为父类引用无法直接调用子类特有的方法
}
}
除非强制转型/在子类中声明一个新方法调用super接口/父类函数中添加final,否则无法使用父类中的方法
class Animal {
void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Dog barks");
}
void makeAnimalSound() {
super.makeSound();
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Dog(); // 运行时多态,父类引用指向子类对象
animal.makeSound(); // 调用子类中重写的方法,输出:Dog barks
//没有强制转型 但建立了一个新的对象。
Dog dog = new Dog();
dog.makeAnimalSound(); // 调用父类中的方法,输出:Animal makes a sound
}
}