一。我对几个概念的理解:
1.Java中的多态:指的是它的可以有多种状态的一种特性,是一种它特性上的名词描述 (一个父引用可以指向多个不同的实际子对象)
ps:多态性中,例如方法的重载(编译时多态,静态的)、重写等都是组成多态性的成分之一;但好像大部分人默认将类似A a = new B;(B继承于A,B覆写了A方法)的直接称为多态(运行时多态,动态连接绑定)。(那我也随流吧)
自己的较深理解:Animal animal = new Cat(),将父类引用指向了子类猫的实例对象。这样做正是深刻体现了Java的多态性,也就是一个父对象可以有多个指向的实际子类对象,因为子类对象中覆写了方法,每个不同子对象的方法行为不同,父类也就可以调用同一个方法却因为实际指向的子对象不同而可以有多种不同的动作了。而这样做的作用意义大概主要是可以提高代码的复用性,也可以较大程度减少耦合度太高导致的后期维护的困难,但性能影响较大,适当使用。
别人大神专业的理解:
所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
Animal animal = new Cat();
Animal animal = new Dog();
animal.call();(此时调用父类引用的call方法却可以因为不同实际对象而有不同行为)
(向上转型与向下转型(强制转换)体现了多态性;是对象造型的知识点;)
2.向上转型:指将具有继承关系的子类转为父类的这个操作,举例也就是就将(子类)猫转为了(父类)动物的操作。
ps:Animal animal = new Cat()的这个操作;(好像也可以写成Animal animal =(Animal) new Cat(),类似于强转换的形式但是,是将子类转为父类,但好像是因为自动转换了,不写也一样);
3.向下转型:与向上转型相反;将指向子类实例的父类引用转为子类的操作;
ps:拥有Animal animal = new Cat()的前提条件;即为:必须是先有向上转型的父类引用才能进行此操作,否则出异常;
然后Cat cat = (Cat)Animal()的这个操作即为向下转型,也叫强制转换;
转换后的结果就是又将其变为了正常的相应子类对象。
经常需要用instanceof关键字来判断两个用来转换的对象的类型(返回true或false),防止出现异常;
二。使用时的理解:一句话:父类引用实际上就是获得了子类对象而已,用的时候总体按照继承子类的知识(注意变量隐藏等问题)的使用方法即可。。。。。
但要注意的几点:
1.只能获得子类中继承父类本身同名的覆盖的方法;
2.子类若有自身独有的方法,父类无法获得
3,子类中与父类中同名的变量和独有的变量,父类都不能直接入 A.name这种形式获得,因为这个引用指向的其实就是变成了除了覆盖的方法不同其他与父类完全相同的子对象;可以通过方法返回比如A.getName()返回子类的属性name,但要注意这个方法父类也本身必须拥有且子类有覆盖,因为没覆盖的话则又是指向类父类自己的变量;
4.若子类有覆盖父类的方法,父类引用调用的是子类中的相应方法;
代码:(未修改完善)
public class Animal {
String name = "dongwu";
int weight=0;
void getName() {
System.out.println(getClass().toString()+"...name= " + name);
}
void getWeight() {
System.out.println(getClass().toString()+"....weight: " + weight);
}
void call() {
System.out.println(getClass().toString()+":...." + "I am " + name + "重:" + weight);
}
}
public class Cat extends Animal {
//String name;
int weight;
Cat() {
name = "cat";
weight=6;
}
void getName(){
// super.getName();
System.out.println(getClass().toString()+"....name: "+name);
}
}
测试类:
public class Test {
/**
*
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//
Animal animalDog = new Dog();
Animal animalCat = new Cat();
//有覆盖,调用了子类方法;预期为cat
animalCat.getName();
//没有覆盖,调用的是原先父类的那个方法,获得是父类的weight
animalCat.getWeight();
//下面两个获得都是父类自己的变量值,因为父类name在cat类中被赋值了,所以变了
System.out.println(animalCat.name);
System.out.println(animalCat.weight);
}
}
运行结果:
class cn.ucai.duotai.Cat....name: cat
class cn.ucai.duotai.Cat....weight: 0
cat
0
总结:
多态的核心在于:可以通过父类调用子类(覆盖)的方法。而父类可以有很多子类,也就可以父类去调用实际持有的
各种子对象的方法,从而有了不同的运行状态。构成了多态性。
使用时还有就是这样想像:就是它还是子类本身,但是由于转成父类了,这个被转化的子类除了覆盖的方法改变了,而其他变得与原先父类没啥不同;调用覆盖的方法就是调用了原先子类的方法;与子类 cat c = new cat();的不同就是不能直接形如Animal.name去访问到子类的name(变量),得到的是父类自己的;需要调用覆盖的getname()方法得到。如果子类没覆盖,AnimalCat.getName()得到的也只是父类Animal自己的name而已,这个与正常的继承中的知识一样。
。。。。。。。。。。。。。。。。。。。。。。。
转的别人家的话:
设计模式的角度,根据里氏代换原则,任何基类可以出现的地方,子类一定可以出现。
向上转型 可以理解成子类包含父类的所有信息,所以父类替换成子类是没有任何问题。
向下转型 子类替换成父类,因为父类是有可能不含有子类的相关信息的。需要人为确认这样
转化是没有问题的。所以语法上需要强制转换。
。。。。。未完善,待续