Java学习——面向对象之多态
多态的概念:多态指的是某一个事物,在不同时刻表现出来的不同状态。在面向对象语言当中,其表现的是接口的不同实现方式。也就是说允许父类的引用指向子类。
举个例子:
Dog dog = new Dog();
Animal an = new Dog();
我们设计一个Dog类,将其对象new出来,用它本身的引用去指向。当然我们也可以用其父类Animal去指向new出来的Dog对象。也就是说,狗是动物的一种,它就可以用Animal的引用去指向Dog对象。
多态的前提:
1.要有继承关系:多态使用父类的引用指向子类的对象,所以继承是第一个条件
2.要有父类引用指向子类对象:父类 f = new 子类();
3.要有方法重写:这个其实没有也是可以的,但如果没有方法重写就没有意义了
多态的优点与缺点:
优点:
1.提高了代码的维护性:由继承来保证的
2.提高了代码的扩展性:由多态保证,多态的意义就是在于提高代码的扩展性
缺点:
1.不能使用子类特有的功能
如何解决:向下转型,看如下代码:
public class Test {
public static void main(String[] args) {
Fu f = new Zi();
//f.fly(); 当我们调用子类特有的功能时,程序会报错
//那么我们将该对象的引用向下转型为子类的引用,不就可以调用子类的特有方法了吗
Zi z = (Zi)f;
z.fly();
//也可以直接一步实现向下转型加调用
//((Zi) f).fly();
}
}
//父类
class Fu{
public void eat(){
System.out.println("父类,吃饭");
}
}
//子类
class Zi extends Fu{
//子类重写父类的eat方法
@Override
public void eat() {
System.out.println("子类,吃饭");
}
//子类特有的方法fly
public void fly(){
System.out.println("子类特有功能,飞");
}
}
多态中成员的访问特点:
1.成员变量
编译看左边,运行看左边。
public class Test {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.num);//10 这里用的是父类的引用所以打印的是父类的num:10
}
}
class Fu{
//父类成员变量
int num=10;
}
class Zi extends Fu{
//子类成员变量
int num = 20;
}
//输出结果:10
2.构造方法
创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化。
public class Test {
public static void main(String[] args) {
//在创建多态对象时,会先对父类进行初始化,所以先执行父类的构造。再对子类进行初始化
Fu f = new Zi();
}
}
class Fu{
//父类构造
public Fu() {
System.out.println("父类构造方法");
}
}
class Zi extends Fu{
//子类构造
public Zi() {
System.out.println("子类构造方法");
}
}
/*
输出结果:
父类构造方法
子类构造方法
*/
3.成员方法
编译看左边,运行看右边。
public class Test {
public static void main(String[] args) {
Fu f = new Zi();
//先去访问父类的eat方法,发现子类重写了eat方法,所以以子类重写过后的为准
f.eat();
}
}
class Fu{
//父类eat方法
public void eat(){
System.out.println("父类吃饭");
}
}
class Zi extends Fu{
//子类重写了父类的eat方法
@Override
public void eat() {
System.out.println("子类吃饭");
}
}
/*
输出结果:子类吃饭
*/
4.静态方法
编译看左边,运行看左边。
(静态和类相关,算不上重写,所以,访问还是左边的)
public class Test {
public static void main(String[] args) {
Fu f = new Zi();
/*
直接以父类eat方法为准,因为静态成员属于类,所以子类的eat方法不是重写。
用父类的引用肯定访问的时父类的eat方法
*/
f.eat();
}
}
class Fu{
//父类静态eat方法
public static void eat(){
System.out.println("父类吃饭");
}
}
class Zi extends Fu{
//子类静态eat方法
public static void eat() {
System.out.println("子类吃饭");
}
}
/*
输出结果:父类吃饭
*/