JAVA面向对象中继承的子父类成员函数的内存图解,以及成员函数中的覆盖的应用.

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_42947972/article/details/102034654

JAVA中继承子父类成员函数的使用

我把成员函数理解为就是类里面的功能,或者说是方法.

子父类的成员函数调用可以是这样的
例如:

class Fu{
	void show1()
	{
		System.out.println("fu show run");
	}
}
class Zi extends/*继承*/ Fu{
	void show2()
	{
		System.out.println("zi show run");
	}
}
public class ExtendsDemo{
	public static void main(String[] args){
		Zi z = new Zi();
		z.show1();
		z.show2();
	}
}

这样我们new了一个叫z的对象,我们可以同时调用两个类中的方法.

在内存它是这样子的:
在这里插入图片描述
随着编译,类加载进入方法区,main函数进栈
在这里插入图片描述
由于Zi 类是Fu 类的子类,所欲 Zi类里面有一个super的指向了父类
在这里插入图片描述
mian函数里面创建了一个叫z的对象,于是进堆了.
这时我们调用了方法:z.show1();
这时z就通过堆内存地址找到Zi,然后先查找zi里面的方法区有没有show1();
发现没有,然后又发现Zi里有个父类,即通过super进入父类里面查找,发现有,
于是执行.

z调用另一个方法:z.show2();
这时z就通过堆内存地址找到Zi,然后先查找zi里面的方法区有show2();于是就执行了.

当子父类里面的成员函数名都是一样的时候,其实也是一样理解的时候
如:

class Fu{
	void show()
	{
		System.out.println("fu show run");
	}
}
class Zi extends/*继承*/ Fu{
	void show()
	{
		System.out.println("zi show run");
	}
}
public class ExtendsDemo{
	public static void main(String[] args){
		Zi z = new Zi();
		z.show();
	}
}

我们的输出结果是:zi show run

具体我们可以看一下图解
在这里插入图片描述
当调用z方法时:z通过地址找到推的对应内存,然后先找自己类里面的方法名,发现有,直接就执行了.

我们把这种叫做覆盖.

 当子父类中出现成员函数一摸一样的情况,会运行子类的函数.
    这种现象,称为覆盖操作,这是函数在子父类中的特性.

    函数的两个特性:
            1.重载. 同一个类中.overload
            
            2.覆盖. 子类中. 覆盖也称为重写.或者叫覆写.override

    覆盖注意事项:
        1.子类方法覆盖父类方法时,子类权限必须大于等于父类的权限.
        (当父类的方法是void时,子类的方法也是void时,它们两个的权限是相同的,可以进行覆盖操作.)
        (但当父类的方法是public,子类的方法是void时,这时子类就不能对父类进行覆盖操作.)
        
        2.静态只能覆盖静态,或被静态覆盖.
        (当父类的方法是private时,子类的方法也是private时,它们两个都是静态的,可以进行覆盖操作.)
          (当父类的方法不是private时,子类的方法是private时,它们可以进行覆盖操作.)
          (但当父类的方法是private,子类的方法不是时,这时子类就不能对父类进行覆盖操作.)

覆盖应用

这里什么时候使用覆盖操作我们可以这样理解:
假定我们现在手机只有一个打电话的功能
这个功能我们把它封装在一个类中(这里就是简单的比喻,实际代码量肯定很多)

class Phone{
	void show()
	{
		System.out.println("通话");
	}
}
public class PhoneDemo{
	public static void main(String[] args){
		Phone p = new Phone();
		p.show();
	}
}

然后突然有一天,我们想要给这个手机增加来电大头贴和电话视频的功能,也就是升级.

这时我们肯定是不能直接通过修改那个已经封装好的类的.
因为一修改肯定不是修改一处,而是要修改很多东西,这会给升级带来灾难.
所以一般不在源代码进行规模的修改.

我们会定义新一个类,然后在这个新的类写需要的新功能,然后继承上面的版本的类.
然后把new的Phone类修改成这个新的NewPhone类就行了.
即:

class Phone{
	void show()
	{
		System.out.println("通话");
	}
}
class NewPhone{
	void show()
	{
		super.call();
		System.out.println("来电大头贴");
		System.out.println("电话视频");
	}
}
public class PhoneDemo{
	public static void main(String[] args){
		NewPhone p = new NewPhone();
		p.show();
	}
}

什么时候使用覆盖操作?

        当对一个类进行扩展时,子类需要保留父类的功能声明,
        但是要定义子类中该功能的特有内容时, 就使用覆盖操作完成.

猜你喜欢

转载自blog.csdn.net/weixin_42947972/article/details/102034654