继承知识点总结

1.继承的概念

继承——面向对象的三大特征之一,也是实现软件复用的重要手段。与C++不同的是,java中的继承为单继承,每个子类只有一个直接父类;java的继承通过extends关键字来实现,使用了extends的类被称为子类,extends后所标注的类即为父类的类名。

父类的包含范围比子类大。(父类 > 子类)

举个例子,假如一个父亲姓王(String),家训是爱国(类比java里的方法),那么作为儿子一般会继承父亲的姓氏,继承家训:

父类里的代码:

public class Father {

public String familyname;

public void spirit(){

System.out.println("你的家训是:爱国");

}

}

子类里的代码:

public class Son extends Father {

public static void main(String[] args) {

//对Son创建对象

Son son = new Son();

//Son里没有spirit这个方法,但是继承了Father后,就可以使用父类的这个方法

son.spirit();

//Son里没有familyname这个变量,Son同样通过继承的方式可以访问这个变量

son.familyname = "王";

System.out.println("你的姓氏是:" + son.familyname);

}

}

2.父类方法的重写

2.1方法重写(方法覆盖)

当子类中包含着与父类同名的方法,这就是子类对父类的方法的重写,也称为方法覆盖;要对父类方法进行重写时,注意以下几点:

  • 方法名、形参列表必须相同;
  • 子类的方法重写时必须必父类的方法返回值类型范围更小或相等(父类的包含范围要比子类大)、子类的异常抛出类型范围同样需要如此;
  • 子类的方法访问权限应比父类方法的访问权限更大或者相等;
  • 子类方法与需要重写的父类方法需同为类方法或同为实例方法。

紧接着上面的例子,儿子对于父亲留下的家训(spirit方法)想做修改完善,想把家训改成:爱国、敬业、诚信、友善,那么就要对继承来的spirit方法进行方法重写:

父类代码(不变):

public class Father {

public String familyname;

public void spirit(){

System.out.println("你的家训是:爱国");

}

}

子类代码(方法重写):

public class Son extends Father {

public static void main(String[] args) {

//对Son创建对象

Son son = new Son();

//Son里没有spirit这个方法,但是继承了Father后,就可以使用父类的这个方法

son.spirit();

//Son里没有familyname这个变量,Son同样通过继承的方式可以访问这个变量

son.familyname = "王";

System.out.println("你的姓氏是:" + son.familyname);

}

//对父类的方法重写

public void spirit() {

System.out.println("家训是:爱国、敬业、诚信、友善");

}

}

2.2父类中有private访问权限时

我在java的封装中介绍过private访问控制符,private修饰的变量、方法仅能在该类中被访问,即使这个类成为了父类被继承,子类也无法进行访问;如果子类中定义了与父类中private方法相同的一个方法,那也不能算为重写,那只是子类重新定义了一个方法。

紧接着上面的示例,继续拓展,比如父亲有抽烟的习惯,这种习惯儿子不会百分百的继承过来,那么抽烟这个习惯就是父亲自己的习惯,儿子不继承:

父类代码:

public class Father {

public String familyname;

public void spirit(){

System.out.println("你的家训是:爱国");

}

private void smoke() {

System.out.println("抽烟的习惯");

}

}

子类代码:

public class Son extends Father {

public static void main(String[] args) {

//对Son创建对象

Son son = new Son();

//Son里没有spirit这个方法,但是继承了Father后,就可以使用父类的这个方法

son.spirit();

//Son里没有familyname这个变量,Son同样通过继承的方式可以访问这个变量

son.familyname = "王";

System.out.println("你的姓氏是:" + son.familyname);

}

//对父类的方法重写

public void spirit() {

System.out.println("家训是:爱国、敬业、诚信、友善");

}

}

3.super限定

如果需要子类方法中调用父类被重写的实例方法,可以利用super限定进行调用该实例方法。(super不能被用在被static修饰的方法中)

并且,super限定的查找顺序为:

  • 本方法中是否存在super限定的方法或变量;
  • 本类中是否有super限定的方法活腻变量;
  • 父类中是否有super限定的方法或变量,如果没有,则继续上溯到父类的父类中是否存在,一直上溯到java.lang.Object类,如果没有搜寻到,则报错。

继续我之前的事例,假如儿子需要翻看爷爷时期的家训,那么就要跳过父亲的家训查看,所以我注释掉了父亲的spirit方法,通过super实现了son中调用grandfather类的方法:

爷爷类里的代码:

public class Grandfather {

public String familyname = "王";

public void spirit(){

System.out.println("你的家训是:诚信");

}

}

父亲类里的代码:

public class Father extends Grandfather {

public String familyname = "王";

/*

* 当son需要访问grandfather的spirit方法时

* 此时father里的该方法必须删除掉,即使用private修饰也不行

* 只有这样,son通过super才可以访问到grandfather的方法

*/

// public void spirit(){

// System.out.println("你的家训是:爱国");

// }

private void smoke() {

System.out.println("抽烟的习惯");

}

}

儿子类里的代码:

public class Son extends Father {

public static void main(String[] args) {

//对Son创建对象

Son son = new Son();

//Son里没有spirit这个方法,但是继承了Father后,就可以使用父类的这个方法

son.spirit();

//Son里没有familyname这个变量,Son同样通过继承的方式可以访问这个变量

System.out.println("你的姓氏是:" + son.familyname);

son.UseSuper();

}

//对父类的方法重写

public void spirit() {

System.out.println("家训是:爱国、敬业、诚信、友善");

}

//super的使用,访问grandfather的方法

public void UseSuper() {

super.spirit();

}

}

4.父类构造器的调用

子类不能通过继承获得父类的构造器,但是子类构造器里可以调用父类构造器的初始化代码。

在一个构造器中调用另一个重载的构造器在其使用this;在子类构造器中调用父类的构造器可以使用super。

希望大家结合注释看代码:

父类中的代码:

public class Father {

double size;

String name;

//父类的构造器

public void use(double usize,String uname) {

this.name = uname;

this.size = usize;

}

}

子类中的代码:

public class Son extends Father {

public int age;

//子类的构造器

public Son(int age,double usize,String uname) {

//子类中没有double、String型的变量,但通过super可以借用父类中的构造器代码

//借用了父类的构造器进行了初始化

super.use(usize, uname);

this.age = age;

}

public static void main(String[] args) {

//使用son进行赋值

Son son = new Son(18,50.1,"whl");

System.out.println("age:" + son.age);

System.out.println("size:" + son.size);

System.out.println("name:" + son.name);

}

}

另外,当父类中通过this调用了同类中的重载构造器时,会一次执行父类的多个构造器。这个点不做过多的阐述,代码如下:

class Grandfa{

public Grandfa(){

System.out.println("empty");

}

}

class Dad extends Grandfa {

public Dad(String name) {

System.out.println("Dad单形参构造器输出name:" + name);

}

public Dad(String name,int age) {

//调用同一个重载的构造器

this(name);

System.out.println("Dad双形参构造器输出age:" + age);

}

}

public class Son extends Dad {

public Son(String name) {

//显示父类有两个参数的构造器

super("java",3);

// TODO Auto-generated constructor stub

System.out.println("son构造器输出");

}

public static void main(String[] args) {

new Son(null);

}

}

主程序只创建了对象,但是构造器里的操作都执行了,输出的结果为:

empty

Dad单形参构造器输出name:java

Dad双形参构造器输出age:3

son构造器输出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值