携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情
子类与父类之间如何实现多态?首先,多态有三个必要的条件:继承、重写、父类引用指向子类对象。在java中,多态的核心表现主要有两种:方法多态和对象多态。
方法多态
- 方法重写
子类重写父类的方法,同一个父类的方法不同的子类可以有不同的实现
public class PenkException {
private String message;
public String getMessage() {
return message;
}
}
public class BusinessException extends PenkException {
@Override
public String getMessage() {
return super.getMessage();
}
}
- 方法重载
同一个方法名称,通过不同的参数的类型或者不同的参数个数来调用不同的方法,代码示例如下:
public class BusinessException extends PenkException {
public BusinessException(RetCodeEnum retCodeEnum) {
super(retCodeEnum);
}
public BusinessException(String message) {
super(message);
}
public BusinessException(RetCodeEnum retCodeEnum, String message) {
super(retCodeEnum, message);
}
public BusinessException(RetCodeEnum retCodeEnum, String message, Errors data) {
super(retCodeEnum, message, data);
}
}
提供了多个构造器,名称相同,但是参数不一样,属于构造器重载
重写和重载都是实现多态的方式,区别在于重载是实现的编译时的多态性,而重写实现的是运行时的多态性,重载发生在同一个类中,而重写是发生子类与父类之间
以上为大多数文章对于方法多态的解释。个人认为重载并不是多态,重载在方法调用前就已经确定了调用某个方法,属于早绑定。多于多态而言,只有运行到调用某个方法时,解析器才能确定调用哪一个方法,这属于晚绑定。引用一句Bruce Eckel的话:“不要犯傻, 如果它不是晚绑定,它就不是多态。所以说,我认为重载并不是多态的一种提现,重载也不满足于多态的三个必要条件(继承、重写、父类引用指向子类对象)
对象多态
- 向上转型
发生向上转型后调用的方法首先是子类重写后的父类方法,如果子类没有重写父类的方法,那还是调用的父类中的方法,传统的对象只能调用自己类中的方法,发生向上转型后,对象不仅可以调用自己类中的方法,还可以调用子类重写后的方法。 注意:向上转型不能调用子类中自己定义的方法
class A {
public void fun1() {
System.out.println("我是A,fun1。");
}
public void fun2() {
System.out.println("我是A,fun2。");
}
}
class B extends A {
public void fun1() {
System.out.println("我是B,fun1。");
}
public void fun3() {
System.out.println("我是B,fun3。");
}
}
public static void main(String[] args) {
B b = new B();
A a = b;
a.fun1(); // 我是B,fun1。
a.fun2(); // 我是A,fun2。
a.fun3(); // 编译不通过
}
- 向下转型
向下转型必先向上转型,因为要通过向上转型先确定子类和父类的关系,如B继承A,如果直接通过A转型为B(向下转型)的话,程序并不知道A的子类是谁(有可能A还有一个子类C,程序不知道是转为B还是转为C)。
而向上转型再向下转型,先B转型为A(java是单继承,明确的知道要转为父类A),然后A再转型为B,此时程序就可以明确的知道A和B是父子类关系,此时就可以向下转型。向下转型,可以调用父类和子类中的所有方法
class A {
public void fun1() {
System.out.println("我是A,fun1。");
}
public void fun2() {
System.out.println("我是A,fun2。");
}
}
class B extends A {
public void fun1() {
System.out.println("我是B,fun1。");
}
public void fun3() {
System.out.println("我是B,fun3。");
}
}
class C extends B {
public void fun1() {
System.out.println("我是C,fun1。");
}
public void fun4() {
System.out.println("我是C,fun4。");
}
}
class Test {
public static void main(String[] args) {
C b = new C();
A a = b;
B b1 = (B) a;
b1.fun1(); // 我是C,fun1。
b1.fun2(); // 我是A,fun2。
b1.fun3(); // 我是B,fun3。
}
}