java的继承通过什么关键字来实现_java面向对象(二)之继承

继承

介绍

继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。继承即常说的is-a关系。子类继承父类的特征和行为,使得子类具有父类的各种属性和方法。或子类从父类继承方法,使得子类具有父类相同的行为。

例子:

比如可以先定义一个类叫车,车有以下属性:车体大小,颜色,方向盘,轮胎,而又由车这个类派生出轿车和卡车两个类,为轿车添加一个小后备箱,而为卡车添加一个大货箱。

继承所表达的就是一种对象类之间的相交关系,它使得某类对象可以继承另外一类对象的数据成员和成员方法。若类B继承类A,则属于B的对象便具有类A的全部或部分性质(数据属性)和功能(操作),我们称被继承的类A为基类、父类或超类,而称继承类B为A的派生类或子类。

表示父类和子类的术语:父类和子类、超类和子类、基类和派生类,他们表示的是同一个意思。

为什么需要继承

开发动物类,其中动物分别为企鹅以及老鼠,要求如下:

企鹅:属性(姓名,id),方法(吃,睡,自我介绍)

老鼠:属性(姓名,id),方法(吃,睡,自我介绍)

企鹅和老鼠都是动物我们是不是可以写一个动物类,这样代码是不是简洁了许多。有的人说我就想单独建两个类写这个属性,我只能告诉你可以,但这好比,你父亲给你了几百万,你偏不要,把这些钱扔了非要自己去挣,你想这样我也没办法。既然java给我们提供了继承我们就要好好用这样会大大提高我们的开发效率,比如:维护性提高了,代码也更加简洁,提高代码的复用性也提高了(复用性指可以多次使用,不用再多次写同样的代码)。

作用:

1、继承可以减少重复的代码。比如父类已经提供的方法,子类可以直接使用,不必再去实现。

2、继承是多态性的前提。当然使用继承的同时也提高了类的耦合度。

当你不需要父类的属性时,可以覆盖调原属性。

Java继承分类

继承分为单继承和多重继承。单继承是指一个子类最多只能有一个父类。多继承是一个子类可以有二个以上的父类。由于多继承会带来二义性,在实际应用中应尽量使用单继承。Java语言中的类只支持单继承,而接口支持多继承。Java中多继承的功能是通过接口(interface)来间接实现的。

继承实现

继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。

继承的初始化顺序:

父类—>父类的初始化对象中的属性—>父类的构造方法—>子类—>子类的初始化对象中的属性—>子类的构造方法

若有构造方法:则先执行属性,再执行构造方法

若构造方法中没有对name属性进行赋值,则name的值为类属性所赋的值

extends关键字

在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。

/*动物类*/

public class Animal {

private String name;

private int id;

public Animal(String myName, String myid) {

//初始化属性值

}

public void eat() { //吃东西方法的具体实现 }

public void sleep() { //睡觉方法的具体实现 }

}

/*企鹅是动物,所以可以继承动物类*/

public class Penguin extends Animal{

//企鹅继承了动物类,所以拥有了动物类的属性和方法

}

implements关键字

使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。

public interface A {

public void eat();

public void sleep();

}

public interface B {

public void show();

}

public class C implements A,B {

}

super 与 this 关键字

super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。

注:

1.只能在构造方法或实例方法内使用super关键字,而在静态方法和静态代码块内不能使用super关键字

2.如果父类中的成员变量和方法被定义为private类型,那么子类永远无法访问它们,如果试图采用super.var的形式去访问父类的private类型的var变量,就会导致编译错误

this关键字:指向自己的引用,表示当前正在调用此方法的对象引用。

注:

1.当具多个重载的构造器时,且一个构造器需要调用另外一个构造其,在其第一行使用this(param)形式调用,且只能在第一行;

2.当对象中一个方法需要调用本对象中其他方法时,使用this作为主调,也可以不写,实际上默认就是this作为主调;

3.当对象属性和方法中的局部变量名称相同时,在该方法中需要显式的使用this作为主调,以表示对象的属性,若不存在此问题,可以不显式的写this。

其实,其牵涉到的一个问题就是变量的查找规则:先局部变量 => 当前类中定义的变量 => 其父类中定义的可以被子类继承的变量 => 父类...

这块要完全理解需要看上面我写的“继承的初始化顺序”从这里可以看到程序是如何初始化的。

/**

* 父类

* @author gacl

*

*/

class FatherClass {

public int value;

public void f() {

value=100;

System.out.println("父类的value属性值="+value);

}

}

/**

* 子类ChildClass从父类FatherClass继承

*/

class ChildClass extends FatherClass {

/**

* 子类除了继承父类所具有的valu属性外,自己又另外声明了一个value属性,

* 也就是说,此时的子类拥有两个value属性。

*/

public int value;

/**

* 在子类ChildClass里面重写了从父类继承下来的f()方法里面的实现,即重写了f()方法的方法体。

*/

public void f() {

super.f();//使用super作为父类对象的引用对象来调用父类对象里面的f()方法

value=200;//这个value是子类自己定义的那个valu,不是从父类继承下来的那个value

System.out.println("子类的value属性值="+value);

System.out.println(value);//打印出来的是子类自定义的那个value的值,这个值是200

/**

* 打印出来的是父类里面的value值,由于子类在重写从父类继承下来的f()方法时,

* 第一句话“super.f();”是让父类对象的引用对象调用父类对象的f()方法,

* 即相当于是这个父类对象自己调用f()方法去改变自己的value属性的值,由0变了100。

* 所以这里打印出来的value值是100。

*/

System.out.println(super.value);

}

}

/**

* 测试类

*/

public class TestInherit {

public static void main(String[] args) {

ChildClass cc = new ChildClass();

cc.f();

}

}

运行结果:

父类的value属性值=100

子类的value属性值=200

200

100

分析:

执行   ChlidClass cc = new ChlidClass();

首先在栈空间里面会产生一个变量cc,cc里面的值是什么这不好说,总而言之,通过这个值我们可以找到new出来的ChlidClass对象。由于子类ChlidClass是从父类FatherClass继承下来的,所以当我们new一个子类对象的时候,这个子类对象里面会包含有一个父类对象,而这个父类对象拥有他自身的属性value。这个value成员变量在FatherClass类里面声明的时候并没有对他进行初始化,所以系统默认给它初始化为0,成员变量(在类里面声明)在声明时可以不给它初始化,编译器会自动给这个成员变量初始化,但局部变量(在方法里面声明)在声明时一定要给它初始化,因为编译器不会自动给局部变量初始化,任何变量在使用之前必须对它进行初始化。

子类在继承父类value属性的同时,自己也单独定义了一个value属性,所以当我们new出一个子类对象的时候,这个对象会有两个value属性,一个是从父类继承下来的value,另一个是自己的value。在子类里定义的成员变量value在声明时也没有给它初始化,所以编译器默认给它初始化为0。即(父类的value为0,子类的value为0;)

执行第二句话:   cc.f();

当new一个对象出来的时候,这个对象会产生一个this的引用,这个this引用指向对象自身。如果new出来的对象是一个子类对象的话,那么这个子类对象里面还会有一个super引用,这个super指向当前对象里面的父对象。所以相当于程序里面有一个this,this指向对象自己,还有一个super,super指向当前对象里面的父对象。

这里调用重写之后的f()方法,方法体内的第一句话:“super.f();”是让这个子类对象里面的父对象自己调用自己的f()方法去改变自己value属性的值,父对象通过指向他的引用super来调用自己的f()方法,所以执行完这一句以后,父对象里面的value的值变成了100。接着执行“value=200;”这里的vaule是子类对象自己声明的value,不是从父类继承下来的那个value。所以这句话执行完毕后,子类对象自己本身的value值变成了200。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值