Java自学十四课之类的继承之自学笔记

类的继承

1.继承的概念
继承是一种有已有类创建新类的机制。一个新类从现有的类派生出来,现有的类叫父类或超类,新类称为子类。
继承的好处:

  1. 提高了代码的复用性;
  2. 提高了代码的维护性;
  3. 提高累的抽象程度,是指更接近于人类的思维方式。
  4. 让类与类之间产生了关系,是多态的前提

继承的弊端:

  1. 类的耦合性增强了;
  2. 开发的原则:高内聚,低耦合。
    耦合:类与类的关系 内聚:就是自己完成某件事情的能力

Java要求声明的每一个类都有父类,当没有显式的指出父类时,父类隐含为Java.lang包中的Object类。这个类是所有类的直接或间接父类。一个父类可以拥有多个子类,这个父类就是所有子类都有的方法和属性的集合。每一个子类都是父类的特殊化,具体化。

Java单继承。

继承的语法

【类修饰符】 class ClassName 【extends SuperClassName】 【implement interface】{
//类体
}
其中extends是集继承的关键字。
继承中需要注意的是,对于父类中的私有属性和方法。
对于私有属性和方法有两种说法:

  1. 私有属性和方法不能被继承,但可以通过公有方法去访问私有属性。官方文档也是这么解释的。“A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.”
  2. 私有属性也可以继承,但是由于修饰符是private和protected的,,所有对外是不可见的,所以可以用公有方法访问。

覆盖和隐藏

1.隐藏
子类对从父类继承来的属性变量加以重新定义,则从父类继承的属性将被隐藏。
这样子类中就拥有了一个和父类中变量名字一样的变量了,这时候当子类执行继承自父类的操作时,处理的是继承自父类的变量,而当子类执行它自己声明的方法时,所操作的就是它自己声明的变量,而把继承自父类的变量给隐藏了。默认情况下使用的是子类的变量。
上面说了①执行继承自父类的操作时,用的是父类的变量,还有一种方法②可以在子类中使用super.变量名来访问父类的变量。但是必须放在第一行。
这里有一个很好的例子:

package com.ann.test;

import javax.management.remote.SubjectDelegationPermission;

public class BreakLabel {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
	A a=new A();
	a.setx(4);
	a.printa();
	B b=new B();
	b.printb();
	b.printa();
	b.setx(6);
	b.printb();
	b.printa();
	a.printa();

	}

}
class A{
	int x=2;
	public void setx(int i){
		x=i;
	}
	void printa(){
		System.out.println(x);
	}
}
class B extends A{
	int x=100;
	void printb(){
		super.x=super.x+10;
		System.out.println("super.x="+super.x+" x="+x);
	}
}

结果:
4
super.x=12 x=100
12
super.x=16 x=100
16
4

分析一下:1、new了一个类A的对象;
2、父类对象执行父类方法,给x赋为4;
3、父类对象调用父类输出的方法,这时候a对象的x被改为4了;
4、new一个子类B的对象;
5、子类对象执行子类方法,方法中使用super.x使用继承的x,这时候要注意刚才的4对a对象的属性值进行修改的,所以这时候的super.x是被隐藏了的x=2。所以执行完后输出的是12和100;
6、子类对象调用继承的父类方法,这里就是前面的说执行的是来自父类的操作时,用的是父类的变量,这里父类的变量是super.x,刚刚改变了super.x=12,所以输出12。为什么不是14呢?是因为4是a对象的属性值。这里是另外一个对象b了;
7、B类对象b调用继承自父类的方法,所用的变量也就是继承自父类的变量,也就是super.x=2,然后改变这个值为6。
8、子类对象调用子类方法,和第6步一样,,只是这里的super.x不是2了,是刚刚赋值的6,之前不能用4是因为4是a对象的,调用时用的是b对象调用的。而这里可以用6是因为设置值和调用这个方法都是b对象调用的。所以输出16和100;
9、子类对象调用继承自父类的方法,所以用的变量是来自父类的变量super.x,这里的super.x刚刚被改成了16,所以输出16。
10、父类对象a调用自己的方法,输出x,因为之前给a对象的x赋值为4,所以输出是4。

注意,之前自己矛盾的有以下几点,①明明赋值为4了,为什么super.x用的是2来加10,是因为,赋值的4是a对象的,super只是一个单独的从父类继承的对象,没有依赖于对象,所以是2。②super.x虽然是来自父类的变量,但其实是算自己类的变量,加上super只是说这是来自父类的变量,和子类同名的变量加以区别而已。这就是自己类的变量,这点要牢记,所以执行了super.x=super.x+10后,super.x就变了,下次不会再去从父类中取x。而且要记住,子类相应对象改变了super.x,下次这个对象的super.x一定要记得变。

另外有一个重要的点是:如果想子父类都可以改变一个变量的话,可以将这个变量设置成static。需要注意的是,子类可以继承父类的静态属性和方法,但不能重写。
例子如下:
父(Fu)类:

package com.test;
public class Fu {  
    public static void show() {  
        System.out.println("父类的静态方法");  
    }  
    public void method() {  
        System.out.println("父类的一般方法");  
    }  
}  
--------------------- 
作者:jianhaojiang 
来源:CSDN 
原文:https://blog.csdn.net/qq_38584967/article/details/78504131 
版权声明:本文为博主原创文章,转载请附上博文链接!

子(Zi)类:

package com.test;


public class Zi extends Fu {  
    public static void main(String[] args) {  
        Zi zi = new Zi();  
        zi.show();  
        zi.method();  
    }  
    public static void show() {  
        System.out.println("子类的静态");  
    }  
    public void method() {  
        System.out.println("子类的一般方法");  
    }  

}  
--------------------- 
作者:jianhaojiang 
来源:CSDN 
原文:https://blog.csdn.net/qq_38584967/article/details/78504131 
版权声明:本文为博主原创文章,转载请附上博文链接!

输出结果是:
子类的静态方法
子类的一般方法

这样的代码并不能看出来是不是都重写成功的,子类实例化的自己调用自己的方法很正常,并不能看出什么

!!!划重点了!!!

我们用父类对象接收试试,Fu类不变,修改Zi类:

package com.test;


public class Zi extends Fu {  
    public static void main(String[] args) {  
        Fu fu = new Zi();  
        fu.show();  
        fu.method();  
    }  
    public static void show() {  
        System.out.println("子类的静态");  
    }  
    public void method() {  
        System.out.println("子类的一般方法");  
    }  

}  
--------------------- 
作者:jianhaojiang 
来源:CSDN 
原文:https://blog.csdn.net/qq_38584967/article/details/78504131 
版权声明:本文为博主原创文章,转载请附上博文链接!

输出结果是:
父类的静态方法
子类的一般方法

So,看出来了没,我们清楚的看到用父类对象去接收子类实例化对象调用方法的话,结果普通方法输出子类zi的一般方法,表明子类成功重写并且覆盖了父类普通方法,但是静态方法输出的还是父类fu的方法,并没有重写覆盖。
表明子类可以继承父类静态方法但是不能重写,但是完全是可以继承的,现在删除子类定义的show()方法代码,输出同样不变(子类先在自己成员函数找show(),没有找到,然后就去父类找,在父类找到了)说明确实是可以继承的

package com.test;


public class Zi extends Fu {  
    public static void main(String[] args) {  
        Fu fu = new Zi();  
        fu.show();  
        fu.method();  
    }  

    public void method() {  
        System.out.println("子类的一般方法");  
    }  

} 
输出结果是:
      父类的静态方法
      子类的一般方法
--------------------- 
作者:jianhaojiang 
来源:CSDN 
原文:https://blog.csdn.net/qq_38584967/article/details/78504131 
版权声明:本文为博主原创文章,转载请附上博文链接!

好了,接下来是我的理解:
所谓静态就是指:在编译时所分配的内存会一直存在(不会被回收),直到程序退出内存才会释放这个空间,在实例化之前这个方法就已经存在于内存,跟类的对象没什么关系。子类中如果定义了相同名称的静态方法,并不会重写,而应该是在内存中又分配了一块给子类的静态方法,没有重写这一说,只是单纯的名字问题。

2.覆盖(重写)
如果子类不需要从父类继承来的方法,可以自己重新声明,但是声明的方法必须使用相同的方法名、参数列表,但是执行不用的功能,这就叫方法的覆盖,也叫重写。
关键词super可以调用父类的方法。比如super.asd();必须在第一行。

有继承时的构造方法

构造方法可以被重载,但不能从父类那里继承
有继承时的构造方法遵循的原则:

  1. 子类不能从父类继承构造方法;
  2. 好的程序设计方法是在子类的构造方法中调用父类的某一个构造方法;
  3. super关键字也可以泳衣构造方法中,其功能为调用父类的构造方法;
  4. 如果在子类的构造方法的声明中没有明确调用父类的构造方法,则系统在执行子类的构造方法时会自动调用父类的默认的构造方法;
  5. 如果在子类的构造方法的声明中调用父类的构造方法,则调用语句必须出现在子类构造方法的第一行。

这里如果运用到this调用某一个构造方法,那么可以写在无参的构造方法,调用有参的方法,这样在子类就可以不用显式的调用,默认的调用父类无参的构造方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值