所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
Java实现多态有三个必要条件:继承、重写、向上转型。
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
1.
基于继承的实现机制主要表现在父类和继承该父类的一个或多个子类对某些方法的重写,多个子类对同一方法的重写可以表现出不同的行为
public class Wine {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Wine(){
}
public String drink(){
return "喝的是 " + getName();
}
public String toString(){
return null;
}
}
public class JNC extends Wine{
public JNC(){
setName("JNC");
}
public String drink(){
return "喝的是 " + getName();
}
public String toString(){
return "Wine : " + getName();
}
}
public class JGJ extends Wine{
public JGJ(){
setName("JGJ");
}
public String drink(){
return "喝的是 " + getName();
}
public String toString(){
return "Wine : " + getName();
}
}
public class Test {
public static void main(String[] args) {
//定义父类数组
Wine[] wines = new Wine[2];
//定义两个子类
JNC jnc = new JNC();
JGJ jgj = new JGJ();
//父类引用子类对象
wines[0] = jnc;
wines[1] = jgj;
for(int i = 0 ; i < 2 ; i++){
System.out.println(wines[i].toString() + "--" + wines[i].drink());
}
System.out.println("-------------------------------");
}
}
2.
基于接口实现的多态,接口可以是多继承多实现,它能够利用一组相关或者不相关的接口进行组合与扩充,能够对外提供一致的服务接口。所以它相对于继承来说有更好的灵活性。
public class A {
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
}
public class B extends A{
public String show(B obj){
return ("B and B");
}
public String show(A obj){
return ("B and A");
}
}
public class C extends B{
}
public class D extends B{
}
public class Test {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println("1--" + a1.show(b));
System.out.println("2--" + a1.show(c));
System.out.println("3--" + a1.show(d));
System.out.println("4--" + a2.show(b));
System.out.println("5--" + a2.show(c));
System.out.println("6--" + a2.show(d));
System.out.println("7--" + b.show(b));
System.out.println("8--" + b.show(c));
System.out.println("9--" + b.show(d));
}
}
多态的格式:
父类类型 变量名 = new 子类类型();
多态中的成员特点:
多态成员变量:编译运行看左边
e.g. Animal dog = new Dog(); //Animal是引用类型,Dog是实际类型
System.out.println(dog.age) //dog的引用类型是Animal,所以取到的是父类Animal中的值,说白了dog是属于Animal类,Animal中变量的值是多少就通过对象就取得多少
多态的特点:
1.多态情况下,子类和父类存在同名的成员变量时,访问的时父类的成员变量
2.多态情况下,子父类存在同名的非静态成员方法时,访问的是子类中重写的方法
3.多态情况下,子父类存在同名的静态成员变量成员方法时,访问的是父类的成员函数
4.多态情况下,不能访问子类独由的方法
引用类型转换:
- 向上转型
父类类型 变量名 = new 子类类型();
Animal dog= new Dog()
通过由实例变量Dog类new出来的变量dog作为中介,使得引用变量Animal有所指向,从而完成了向上转型
相当于是Animal dog=(Animal) new Dog()
- 向下转型
子类类型 子类变量名=(子类类型)父类变量名
Dog dog1=(Dog)dog;
Dog1.walk;//此时可以使用子类独有的方法了
参考博客:
https://blog.csdn.net/newchitu/article/details/90380094?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168208873416800192280894%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=168208873416800192280894&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-90380094-null-null.142^v86^control_2,239^v2^insert_chatgpt&utm_term=java%E4%B8%AD%E7%9A%84%E5%A4%9A%E6%80%81&spm=1018.2226.3001.4187
https://blog.csdn.net/z972065491/article/details/127220556?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168208873416800192280894%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=168208873416800192280894&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-127220556-null-null.142^v86^control_2,239^v2^insert_chatgpt&utm_term=java%E4%B8%AD%E7%9A%84%E5%A4%9A%E6%80%81&spm=1018.2226.3001.4187