前文
现实生活是多姿多态,但是它也是一片混乱的。那么,能不能在这个混乱中找到共性了。在Java中,提供了封装,将不同的东西划分开来,成为一个一个的类。还有继承,让有关联的类产生了联系,形成了一颗颗类树。这样已经形成了一条条的逻辑。但是每个树的末级节点是很多的,有时候在程序运行的时候,是需要切换不同子类,那么有没有办法用一个变量代替不同的末级节点?
多态
在Java中,提供了除封装和继承以外的第三种特性:多态。字面意思上,多种状态。在Java中,这个状态,个人认为可以指的是不同的类以及类中的方法。用稍微专业点的描述:用一个引用变量可以代替执行多个子类的方法。具体执行那个子类的方法,是在运行期间决定。
多态的实现
想要实现多态,必须满足三个条件:继承,重写,向上转型。
继承案例:
public class Animal {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void eat(){
System.out.println("动物需要吃食物");
}
}
public class Cow extends Animal {
public Cow() {
}
@Override
public void eat() {
super.eat();
System.out.println("牛主要吃青草。");
}
}
public class Bird extends Animal{
public Bird() {
}
@Override
public void eat() {
super.eat();
System.out.println("鸟主要吃虫子。");
}
public void fly(){
System.out.println("鸟可以飞。");
}
}
public class ExtendTest {
public static void main(String[] args) {
Animal bird = new Bird();
Animal cow = new Cow();
bird.setName("鸟");
bird.eat();
// bird.fly(); 子类独有的方法不可以调取
cow.eat();
}
}
输出
动物需要吃食物
鸟主要吃虫子。
动物需要吃食物
牛主要吃青草。
通过案例我们可以看到,多态只能调用子类重写父类的方法,对于子类独有的方法是不可以调取的。但是我们可以把Bird类稍微修改一下:
@Override
public void eat() {
super.eat();
System.out.println("鸟主要吃虫子。");
this.fly();
}
输出:
动物需要吃食物
鸟主要吃虫子。
鸟可以飞。
这样间接调用子类的独有方法是可以的。那这可以推论出什么了?有待思考。
通过实现接口也是可以实现多态,并且因为Java中支持一个类实现多个接口,相对于继承来说,会更加灵活。比如:Map hashMap = new HashMap.
总结
多态的实现条件:必须有继承类或者实现接口,重写父类方法,以及向上转型。
多态调用成员属性和方法:范围是由超类的成员属性和方法决定的,对于引用子类,只有重写了父类的方法的时候,会强制执行子类的重写方法。这个是针对继承实现的多态,对于实现接口实现的多态,因为接口一般是没有成员属性,并且所有方法都是抽象方法,所以都是调用引用子类。
经典案例
可以先自己猜下结果。
public class A {
public String show(D obj){
return "A and D";
}
public String show(A obj){
return "A and A";
}
}
class B extends A{
public String show(B obj){
return "B and B";
}
public String show(C obj){
return "B and C";
}
}
class C extends B{
}
class D extends B{
}
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));
}
}
如果上面程序理解了的话,可以尝试得出下面程序会输出什么结果。
public class Test {
public static void main(String[] args) {
System.out.println(new B(5).getValue());
}
static class A{
protected int value;
public A(int v){
setValue(v);
}
public void setValue(int value){
this.value = value;
}
public int getValue(){
try {
value++;
return value;
} finally {
this.setValue(value);
System.out.println(value);
}
}
}
static class B extends A{
public B(int v) {
super(v);
setValue(getValue() - 3);
}
public void setValue(int value){
super.setValue(2 * value);
}
}
}