多态

Java的3大特性是封装,继承和多态,今天就介绍下多态.

java引用变量有两个类型:一个是编译时类型,一个是运行时类型.编译是类型由申明该变量时使用的类型决定,运行时类型由实际赋值给该变量的对象决定.如果编译时类型和运行时类型不一致,就可能出现所谓的多态.

多态用一句话概括就是:父类的引用指向了子类的对象.

多态可以使代码具有扩展性

下面是不使用多态的一个例子

public class AnimalTest {
	public static void main(String[] args) {
		Dog dog = new Dog();
		dogPlay(dog);
		Cat cat = new Cat();
		catPlay(cat);
	}


	private static void dogPlay(Dog dog) {
		dog.play();
	}


	private static void catPlay(Cat cat) {
		cat.play();
	}
}



public class Cat extends Animal {
	@Override
	public void play() {
		System.out.println("Cat play方法执行了");
	}
}
public class Dog extends Animal {
	
	@Override
	public void play() {
		System.out.println("Dog play方法执行了");
	}
}
public class Animal {
	public void play() {
		System.out.println("animal play方法执行了");
	}
}


该例子没有使用多态,如果后期增加了其他的新类,需要继续往Test类里面增加类似XXXPlay()的方法,不便于扩展.

如果使用多态,则完全不一样,只需改动很少的代码即可实现.

public class AnimalTest2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Dog dog = new Dog();
		animalPlay(dog);
		Cat cat = new Cat();
		animalPlay(cat);
	}

	private static void animalPlay(Animal animal) {
		animal.play();
	}
}
后续有新类产生时,只需要在main方法中改动代码即可.

多态应该注意的知识点:

1.多态时,如果子类复写了父类的方法,在调用时执行的就是子类的方法.

2.如果子类没有复写父类的方法,在调用时执行的就是父类的方法.

3.多态时如果调用子类特有的方法就会报错.

public class AnimalTest {
	public static void main(String[] args) {
		Dog dog = new Dog();
		dogPlay(dog);
		Cat cat = new Cat();
		catPlay(cat);
	}


	private static void dogPlay(Dog dog) {
		dog.play();
	}


	private static void catPlay(Cat cat) {
		cat.play();
	}
}

public class Cat extends Animal {
	@Override
	public void play() {
		System.out.println("Cat play方法执行了");
	}
}
上面例子的执行结果如下:

Cat play方法执行了
animal sing方法执行了

4.构造函数,这一点需要特别注意

多态中,虽然只是创建了子类的对象,但是由于子类可以访问父类的一些方法,成员变量,所以默认会执行父类对应的构造器.

并且执行顺序是:父类构造器方法→子类构造器方法

public class AnimalTest {
	public static void main(String[] args) {
		Animal animal = new Cat();
	}
}

public class Animal {
	
	public Animal() {
		 System.out.println("Animal 构造器方法执行了");
	}
}

public class Cat extends Animal {
	
	 public Cat() {
		 System.out.println("Cat 构造器方法执行了");
	}
}
上面的例子执行的结果如下:

Animal 构造器方法执行了
Cat 构造器方法执行了

但是有一点需要注意,如果构造器中调用了被子类复写的方法时,可能会出现隐藏性的错误.

public class AnimalTest {
	public static void main(String[] args) {
		Animal animal = new Cat();
	}
}

public class Animal {
	
	public Animal() {
		 System.out.println("Animal 构造器方法执行了");
		 play();
	}
	
	public void play() {
		System.out.println("animal play方法执行了");
	}
}

public class Cat extends Animal {
	
	 public Cat() {
		 System.out.println("Cat 构造器方法执行了");
		 play();
	}
	
	@Override
	public void play() {
		System.out.println("Cat play方法执行了");
	}
}
上面的例子执行的结果如下:

Animal 构造器方法执行了
Cat play方法执行了
Cat 构造器方法执行了
Cat play方法执行了

从结果中发现,Animal的构造器方法调用了play方法,而play方法恰好被子类复写了,所以执行的时候父类和子类中都执行的是子类中的paly方法.这样就可能出现意向不到的问题,所以不建议这种用法.

5.多态中成员变量

先看个例子

public class AnimalTest {
	public static void main(String[] args) {
		Animal animal = new Cat();
		System.out.println("num:"+animal.num);
	}
}

public class Animal {
	public int num = 30;
}

public class Cat extends Animal {
	
	public int num = 20;

}
运行结果如下:

num:30

由运行结果可以发现,打印是父类的成员变量的值.

所以如果子类和父类的成员变量是分别处理时,最好二者的名字不要取相同的名字,要加以区分.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值