学习Java有一段时间了,对于多态一直不是半知不解,所以写一篇个人笔记吧,希望有更深刻的记忆。
实例一:未运用多态的的例子
①新建一个Father类
public class Father {
public String func() {
return "Father方法";
}
}
②新建三个Son类,继承Father类,重写方法
public class Son1 extends Father {
public String func() {
return "Son1方法";
}
}
public class Son2 extends Father {
public String func() {
return "Son2方法";
}
}
public class Son3 extends Father {
public String func() {
return "Son3方法";
}
}
③新建一个Test类,包含Main方法
public class Test {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Father father = new Father();
Son1 son1 = new Son1();
Son2 son2 = new Son2();
Son3 son3 = new Son3();
showFather(father);
showSon1(son1);
showSon2(son2);
showSon3(son3);
}
public static void showFather(Father father) {
System.out.println(father.func() + "被调用");
}
public static void showSon1(Son1 son1) {
System.out.println(son1.func() + "被调用");
}
public static void showSon2(Son2 son2) {
System.out.println(son2.func() + "被调用");
}
public static void showSon3(Son3 son3) {
System.out.println(son3.func() + "被调用");
}
}
打印结果:
Father方法被调用
Son1方法被调用
Son2方法被调用
Son3方法被调用
实例一中并没有使用多态机制,下面用实例二来实现,涉及到类型转换。
实例二:
public class Test {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Father father = new Father();
Son1 son1 = new Son1();
Son2 son2 = new Son2();
Son3 son3 = new Son3();
showFather(father);
showFather(son1);
showFather(son2);
showFather(son3);
}
public static void showFather(Father father) {
System.out.println(father.func() + "被调用");
}
}
打印结果:
Father方法被调用
Son1方法被调用
Son2方法被调用
Son3方法被调用
实例二只是简单地将所有方法都改为showFather方法,但是传入的Son对象也是可行的,这是因为Son对象此时被向上转型为Father对象。我觉得这样理解可能更好:Father对象的引用指向了Son对象。
上述代码也可以这样写:
public class Test {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Father father = new Father();
Father son1 = new Son1(); //假设此时Son1类中有其他方法,son1也是无法调用的,必须是重写
Father son2 = new Son2(); //父类的方法才可以向上转型后调用
Father son3 = new Son3();
showFather(father);
showFather(son1);
showFather(son2);
showFather(son3);
}
public static void showFather(Father father) {
System.out.println(father.func() + "被调用");
}
}
说到向上转型,顺带也说下向下转型:
Son1 son1 = (Son1)new Father(); //不可行
Father father = new Son1();
Son1 son1 = (Son1)father; //可行,必须先有一个向上转型才可以正确地向下转型
实例三:抽象类的使用,父类的方法有时只是充当一个接口的作用,它本身并不需要实现什么,所以可以这样改:
public abstract class Father {
public abstract String func();
}
public class Test {
public static void main(String[] args) {
// TODO 自动生成的方法存根
// Father father = new Father(); //抽象类是不可以实例化的,天生就是被继承的命
Father son1 = new Son1();
Father son2 = new Son2();
Father son3 = new Son3();
showFather(son1);
showFather(son2);
showFather(son3);
}
public static void showFather(Father father) {
System.out.println(father.func() + "被调用");
}
}
打印结果:
Son1方法被调用
Son2方法被调用
Son3方法被调用
public interface Father {
public abstract String func();
}
public class Son1 implements Father { //继承改为实现,其他两个子类也是实现父接口
public String func() {
return "Son1方法";
}
}
public class Test {
public static void main(String[] args) {
// TODO 自动生成的方法存根
// Father father = new Father(); //接口是不可以被实例化的,压根不存在构造器。
Father son1 = new Son1();
Father son2 = new Son2();
Father son3 = new Son3();
showFather(son1);
showFather(son2);
showFather(son3);
}
public static void showFather(Father father) {
System.out.println(father.func() + "被调用");
}
}
打印结果:
Son1方法被调用
Son2方法被调用
Son3方法被调用
为什么我在实例二后面会说“我觉得这样理解可能更好:Father对象的引用指向了Son对象。”,这是由于抽象类和接口都是不可以实例化的,但是却可以将其对象的引用指向子类或者实现类的对象而非本身。