继承
来源:互联网 发布:淘宝怎么帮朋友代付款 编辑:程序博客网 时间:2024/05/16 05:33
简介
Java中只支持单继承,即每个类只能有一个直接父类.继承表达的是 is a 的关系.在Java中,所有的Java类都直接或间接地继承了java.lang.Object.Object类是所有Java类的祖先.在定义一个类时,如果没有使用extends关键字,那么这个类直接继承Object类.
继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码,能够大大的提高开发的效率。
同时在使用继承时需要记住三句话:
1、子类拥有父类非private的属性和方法。
2、子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
3、子类可以用自己的方式实现父类的方法。(以后介绍)。
诚然,讲到继承一定少不了这三个东西:构造器、protected关键字、向上转型。
一. 构造器
1.构造器子类是继承不了的,它只能够被调用,而不能被继承,在子类中使用super(),即完成调用。对于继承,子类会默认调用父类的构造器,但是如果没有默认的父类构造器,子类必须要 显示的 指定父类的构造器,而且必须是在子类构造器中做的第一件事(第一行代码)。
“对象构建过程是从父类 ‘向外’ 扩散的,也就是从父类开始向子类一级一级地完成构建。而且我们并没有显示的引用父类的构造器,这就是java的聪明之处:编译器会默认给子类调用父类的构造器。但是,这个默认调用父类的构造器是有前提的:父类有默认构造器。如果父类没有默认构造器,我们就要必须显示的使用super()来调用父类构造器,否则编译器会报错:无法找到符合父类形式的构造器。”
二. producted 关键字;
1.目的:对子类开放权限。对于protected而言,它指明就类用户而言,他是private,但是对于任何继承与此类的子类而言或者其他任何位于同一个包的类而言,他却是可以访问的。
“可以使用protected访问修饰符来限制父类属性和方法的访问权限,但是最好的方式还是将 属性 保持为private(我们应当一致保留更改底层实现),通过protected方法来控制类的继承者的访问权限。”
三. 向上转型;
将子类转换成父类,在继承关系上面是向上移动的,所以一般称之为向上转型。由于向上转型是从一个叫专用类型向较通用类型转换,所以它总是安全的,唯一发生变化的可能就是属性和方法的丢失。这就是为什么编译器在“未曾明确表示转型”活“未曾 指定特殊标记”的情况下,仍然允许向上转型的原因。
super关键字
super之前也提到过,是区别于this一种关键字,他一般表示的是调用方法的对象是父类的对象。那么我们就可以利用它去调用父类的方法,父类的非private的成员变量。当然他和this一样,也有一种特殊的应用,即用它去调用父类的构造器。一般情况在调用子类的构造器之前,会默认先调用父类的默认构造器,如果父类没有默认的构造器,那么我们在子类的构造器中就要明确用super去调用父类的构造器,否则会报错。例子如下:
public class Father { public Father(int a){ System.out.println("这是父类的构造器"); }}public class Son extends Father{ public Son(){ super(1); }}
这里一定要显式的调用父类的构造器,否则编译器无法完成父类对象的构造。关于构造器的顺序,初始化过程等等我们以后再详细讨论。
super主要有两种用法:
1.super.成员变量/super.成员方法;
2.super(parameter1,parameter2….)
第一种用法主要用来在子类中调用父类的同名成员变量或者方法;
第二种主要用在子类的构造器中显示地调用父类的构造器,要注意的是,如果是用在子类构造器中,则必须是子类构造器的第一个语句。private访问修饰符,对于封装而言,是最好的选择,但这个只是基于理想的世界,有时候我们需要这样的需求:我们需要将某些事物尽可能地对这个世界隐藏,但是仍然允许子类的成员来访问它们。
这个时候就需要使用到protected。
protected关键字我们在上篇文章中已经讲过,这里就不说了,我们主要说第三点,向上转型。
向上转型
我们使用继承,主要是因为父类和子类之间存在一个种所属关系,子类确实是父类的一种。比如我们可以把动物当做是父类,子类是猫,狗啊等等。猫,狗确实是动物的一种。动物所拥有的方法,猫,狗都有,所以猫,狗是一种类型的动物,既然如此,我们就可以把猫,狗向上转型成动物类型。这是安全且一定成功的。我们可以看下面的例子。
public class Animal { public void run(Animal animal) { System.out.println("动物在奔跑"); }}public class Dog extends Animal{ public static void main(String[] args) { Animal animal = new Animal(); animal.run(new Dog()); }}
这里Animal类的run方法明确规定传入的参数是Animal类型,但我们传入Dog类型也是可以成功的。这种就是向上转型的一种应用。这种转型总是成功的原因,就是上面所说,Dog其实是比Animal更专业,更独特的类型,可以看做是一个专业的类型向通用的类型转换,由一个更大的类向更小的类转换,这种转换除了会丢失一些方法和属性以外,总会是成功的。关于向上转型还有很多要讲的内容,不过这都要和多态联系到一起,我们以后再说。