Java学习——面向对象之多态

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("子类吃饭");
    }
}

/*
	输出结果:父类吃饭
*/

猜你喜欢

转载自blog.csdn.net/qq_43411550/article/details/89363716