java——子类与继承(知识整理)
子类与父类
在类的声明中,通过使用关键字extends来定义一个类的子类,格式如下:
class 子类名 extends 父类名{
...
}
例如:
class Student extends People{
...
}
Student类定义为People类的子类,People类是Student类的父类。
子类的继承性
所谓子类继承父类的成员变量作为自己的一个成员变量,就好像它们是在子类中直接声明的一样,可以被子类中自己定义的任何实例方法操作,也就是说,一个子类继承的成员应当是这个类的完全意义的成员,如果子类中定义的实例方法不能操作父类的某个成员变量,该成员变量就没有被子类继承;所谓子类继承父类的方法作为子类中的一个方法,就像它们是在子类中直接定义了一样,可以被子类中自己定义的任何实例方法调用。
1.子类和父类在同一包中的继承性
子类自然地继承了其父类中不是private的成员作为自己的成员
x只能在A中操作:
class A {
private int x;
}
class B extends A {
void f(){
x=10;
}
}
x可以在B中操作:
class A {
int x;
}
class B extends A {
void f(){
x=10;
}
}
2.子类和父类不在同一包中的继承性
子类只继承父类中的protected和public访问权限的成员变量作为子类的成员变量(private和友好访问权限的成员变量不会被子类继承)
3.protected的进一步说明
子类与对象
1.子类对象的特点
子类对象可以调用继承的方法,操作没有继承的成员变量
2.关于instanceof运算符
instanceof运算符是Java独有的双目运算符,其左面的操作元是对象,右面的操作元是类,当左面的操作元是右面的类或其子类所创建的对象时,instanceof运算的结果是true,否则是false。
例如:
zhang instanceof Student
成员变量的隐藏和方法的重写
1.成员变量的隐藏
定义子类时,我们仍然可以声明成员变量,一种特殊的情况就是,所声明的成员变量的名字和从父类继承来的成员变量的名字相同(声明的类型可以不同),在这种情况下,子类就会隐藏所继承的成员变量
(1)子类对象以及子类自己定义的方法操作与父类同名的成员变量是指子类重新声明的这个成员变量。
(2)子类对象仍然可以调用从父类继承的方法操作被子类隐藏的成员变量,也就是说,子类继承的方法所操作的成员变量一定是被子类继承或隐藏的成员变量。
class A{
double x=3.14;
}
class B extends A{
int x=10;
void f(){
x++;
System.out.println(x);
}
}
输出结果为:
11
class A{
double x=3.14;
}
class B extends A{
int x=10;
void f(){
x++;
System.out.println(x);
}
}
public class E{
public static void main(String args[]){
B b=new B();
b.f();
b.x=100;//如果b.x=100.01编译不会通过
System.out.println(b.x);
}
}
输出的结果为:
11
100
class A{
double x=3.14;
void nihao(){
x++;
System.out.println(x);
}
}
class B extends A{
int x=10;
void f(){
x++;
System.out.println(x);
}
}
public class E{
public static void main(String args[]){
B b=new B();
b.f();
b.x=100;//如果b.x=100.01编译不会通过
System.out.println(b.x);
b.nihao();
}
}
输出结果为:
11
100
4.14
2.方法重写(Override)//重要
如果子类可以继承父类的某个方法,那么子类就有权利重写这个方法。方法重写是指,子类中定义一个方法,这个方法的类型和父类的方法的类型一致或者是父类的方法的类型的子类型(所谓子类型是指,如果父类的方法的类型是“类”,那么允许子类的重写方法的类型是“子类”),并且这个方法的名字、参数个数、参数的类型和父类的方法完全相同。
子类的如此定义的方法称作子类重写的方法。
重写方法既可以操作继承的成员变量、调用继承的方法,也可以操作子类新声明的成员变量、调用新定义的其他方法,但无法操作被子类隐藏的成员变量和方法。
class A{
int x;
void f(){
x=100;
}
}
class B extends A{
int y;
void f(){
x=100;
y=100;//重写方法既可以操作继承的成员变量、调用继承的方法,也可以操作子类新声明的成员变量、调用新定义的其他方法
}
}
class A{
double x;
void f(){
x=100.01;
}
}
class B extends A{
int y;
int x;
void f(){
x=100;//无法操作被子类隐藏的成员变量和方法。
y=100;
}
}
3.重写的注意事项
重写父类的方法时,不允许降低方法的访问权限,但可以提高访问权限(访问限制修饰符按访问权限从高到低的排列顺序是:public、protected、友好的、private)。
class A{
protected float f(float x,float y){
return x-y;
}
}
class B extends A{
float f(float x,float y){ //非法,因为降低了访问权限
return x+y;
}
}
class C extends A{
public float f(float x,float y){ //合法,提高了访问权限
return x*y;
}
}
super关键字
1.用super操作被隐藏的成员变量和方法
子类一旦隐藏了继承的成员变量,那么子类创建的对象就不再拥有该变量,该变量将归关键字super所拥有,同样子类一旦隐藏了继承的方法,那么子类创建的对象就不能调用被隐藏的方法,该方法的调用由关键字super负责。
因此,如果在子类中想使用被子类隐藏的成员变量或方法就需要使用关键字super。比如super.x、super.play()就是访问和调用被子类隐藏的成员变量x和方法play()。
2.使用super调用父类的构造方法
由于子类不继承父类的构造方法,因此,子类在其构造方法中需使用super来调用父类的构造方法,而且super必须是子类构造方法中头一条语句,即如果在子类的构造方法中没有明显地写出supeer关键字来调用父类的某个构造方法,那么默认地有:super();
final关键字
final关键字可以修饰类、成员变量和方法中的局部变量。
1.final类
可以使用final将类声明为final类。final类不能被继承,即不能有子类。如:
final class A{
...
}
2.final方法
如果用final修饰父类中的一个方法,那么这个方法不允许子类重写,也就是说,不允许子类隐藏可以继承的final方法(老老实实继承,不许做任何篡改)。
class A{
final void f(){
...
}
}
class B extends A{
void f(){ //非法,不允许子类重写
...
}
}
3.常量
如果成员变量或局部变量被修饰为final,那它就是常量。由于常量在运行期间不允许再发生变化,所以要求程序在声明变量时必须指定该常量的值。
class A{
final double PI=3.1415926;
public double getArea(final double r){
//r=r+1; //非法,不允许对final变量进行更新操作
return PI*r*r;
}
public final void speak(){
System.out.println("您好,How's everything here ?");
}
}
public class E{
public static void main(String args[]){
A a=new A();
System.out.println("面积:"+a.getArea(100));
a.speak();
}
}
对象的上转型对象
我们经常说“老虎是动物”、“狗是动物”等。若动物类是老虎类的父类,这样说当然正确,因为人们习惯地称子类与父类的关系是“is-a”关系。但需要注意的是,当说老虎是动物时,老虎将失掉老虎独有的属性和功能。从人的思维方式上看,说“老虎是动物”属于上溯思维方式,下面讲解和这种思维方式很类似的Java语言中的上转型对象。
Animal a;
a=new Tiger();
或
Animal a;
Tiger b=new Tiger();
a=b;
这时,称对象a是对象b的上转型对象(好比说“老虎是动物”)。
(1)上转型对象不能操作子类新增的成员变量(失掉了这部分属性),不能调用子类新增的方法(失掉了一些行为)。
(2)上转型对象可以访问子类继承或隐藏的成员变量,也可以调用子类继承的方法或子类重写的实例方法。上转型对象操作子类继承的方法或子类重写的实例方法,其作用等价于子类对象去调用这些方法。因此,如果子类重写了父类的某个实例方法后,当对象的上转型对象调用这个实例方法时一定是调用了子类重写的实例方法。
继承与多态
我们经常说“哺乳动物有很多种叫声”,比如,“吼”“嚎”“汪汪”“喵喵”等,这就是叫声的多态。
当一个子类有很多子类时,并且这些子类都重写了父类中的某个方法。那么当我们把子类创建的对象的引用放到一个父类的对象中时,就得到了该对象的一个上转型对象,那么这个上转型对象在调用这个方法时就可能具有多种形态,因为不同的子类在重写父类的方法时可能产生不同的行为,比如,狗类的上转型对象调用“叫声”方法时产生的行为是“汪汪”,而猫类的上转型对象调用“叫声”方法时,产生的行为是“喵喵”等等。
多态性就是指父类的某个方法被子类重写时,可以各自产生自己的功能行为。
abstract类和abstract方法
用关键字abstract修饰的类称为abstract类(抽象类)。如:
abstract class A{
...
}
用关键字abstract修饰的方法称为abstract方法(抽象方法),如:
abstract int min(int x,int y);
不允许使用final和abstract同时修饰一个方法或类,也不允许使用static修饰abstract方法,即abstract方法必须是实例方法。
1.abstract类中可以有abstract方法
2.abstract类不能用new运算符创建对象
3.abstract类的子类
4.abstract类的对象作上转型对象
5.理解abstract类