众所周知,java是一门面对对象(Object Oriented Programming,OOP)的编程语言
而OOP的有三大特征:封装,继承,多态
今天我们要说的是继承:
继承的概念:提供一种子类沿用父类通用属性,行为的一种编码方式,java的继承是单继承,所以一个子类只能有一个父类,所有类的隐式父类是objiect:
继承的实现:Java的继承通过extends关键字实现.
实现继承的类被称为子类.
被继承的类被称为父类.
父类和子类的关系, 是一种一般和特殊的关系.
例如水果和苹果的关系, 苹果继承了水果, 苹果是水果的子类, 水果是苹果的父类.
案例:
public class Fruit
{
public double weight;
public void info()
{
System.out.println("我是一个水果! 重:" + weight + "g!");
}
}
接下来定义该Fruit类的子类Apple
public class Apple extends Fruit
{
public static void main(String[] args)
{
//创建Apple对象
Apple a = new Apple();
//Apple 对象本身没有 weight 成员变量
//因为Apple 父类有 weight 成员变量, 所以也可以访问 Apple 对象的 weight 成员变量.
a.weight = 56;
//调用 Apple 对象的 info() 方法
a.info();
//子类继承了父类, 也将获得父类的全部成员变量和方法
}
}
方法的重写:
子类继承了父类, 所以说子类是一个特殊的父类.
大部分时候, 子类总是以父类为基础.
额外增加新的成员变量和方法.
但有一种情况例外: 子类需要重写父类的方法.
例如鸟类都包含了飞翔的方法, 但其中的鸵鸟并不会飞, 因为鸵鸟是鸟的子类, 因此它将从鸟类中获得飞翔的方法, 但这个飞翔的方法显然不适合鸵鸟, 所以鸵鸟这个子类需要重写鸟类(父类)的方法.
public class Bird
{
//Bird 类的 fly() 方法
public void fly()
{
System.out.println("我在天空自由自在的飞翔...啦啦啦");
}
}
下面定义一个 Ostrich 类, 这个类继承了 Bird 类, 同时重写 Bird 类的 fly() 方法.
public class Ostrich
{
//重写 Bird 类的 fly() 方法
public void fly()
{
System.out.println("NND, 我可飞不了, 虽然我有双翅膀, 啦啦啦");
}
public static void main(String[] args)
{
//创建 Ostrich 对象
Ostrich os = new Ostrich();
//执行 Ostrich 对象的 fly() 方法, 将会输出 "...飞不了..."
os.fly();
}
}
执行上面的程序, 将看到执行 os.fly() 时执行的不是 Bird 类的 fly() 方法.
而是执行 Ostrich 类的 fly() 方法.
这种子类包含与父类同名方法的现象称为方法重写(Override). 也被称为方法覆盖.
可以说子类重写了父类的方法, 也可以说子类覆盖了父类的方法
方法重写的规则:
1.方法名相同 / 形参列表相同
2. 子类方法返回值类型应比父类方法返回值类型小或相等. / 子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等.
3.子类方法的访问权限应比父类方法的访问权限大或相等.
当子类覆盖了父类方法后, 子类的对象将无法访问父类中被覆盖的方法.
但可以在子类方法中调用父类中被覆盖的方法.
如果需要在子类方法中调用父类中被覆盖的方法, 则可以使用super(被覆盖的是实例方法) 或者 父类类名(被覆盖的是类方法) 来作为调用者, 调用父类中被覆盖的方法.
如果父类方法具有 private 访问权限, 则该方法对其子类是隐藏的.
因此子类无法访问该方法, 也就无法重写该方法.
如果子类中定义了一个与父类 private 方法具有相同的方法名 / 相同的形参列表 / 相同的返回值类型的方法, 依然不是重写.
这只是在子类中重新定义了一个新的方法.